How Quest Code Tester for Oracle can help you get rid of bugs in your PL/SQL procedures
Testing code is very important and unfortunately it is also very hard to do. This tutorial provides a quick introduction to Quest Code Tester and shows how you can use it to quickly and easily define, generate and run tests on your PL/SQL code.

Flash tutorial explaining the topic: A brief video that shows you how to use Quest Code Tester to solve the problem posed by this topic.

Step-by-step instructions: Follow these steps to replicate what we show you in the tutorial.

Set up the test cases

Before diving into the details of each of the test cases, use "top down design" to brainstorm the various test cases that you will need. You do this in the Test Case list on the left hand side of Test Builder.

Press the "Add test case" button  to create a new test case and rename the test cases using the following names:

  • Normal usage test case
  • Zero start
  • Negative start and end
  • Null string

Now it is time to provide the details of each test case.

Normal usage test case

  • Click on to the "Normal usage test case" line. You will then see on the right-hand side the Test Case Editor with three areas (steps). You should provide a good, detailed description for your test cases.
  • Move on to Step 2. Inputs. Enter "abcdefg" into STRING_IN
  • Input: enter "2" into START_IN
  • Input: enter "4" into END_IN
  • Input: enter "TRUE" into INCLUSIVE_IN (the default)
  • Move on to Step 3. Outcomes. Now you define what you to expect to happen when the program is run, which usually means that you will compare what was changed by the program to expected results.
  • You will see an initial outcome row, which checks to see if the value returned by the function is equal to another string. So enter "bcd" for the expected results value. And you are done; the test case is now fully defined.

Zero start

Since a value of 0 for START_IN should be treated as a 1 by betwnstr, we will create that test case.

  • Click on the "Normal usage" test case and drag/drop it onto "Zero start". Press OK on the Copy Test case dialog that appears to copy all elements of the test case. Then click on "Zero start." Most of the work is done for you!
  • Input: change "2" to "0" in START_IN
  • For outcome, change value from "bcd" to "abcd" for the expected value.
  • And you are done; the test case is now fully defined.

Negative start and end

You can use betwnstr to grab sub-strings from the back of the string by providing negative values. Let's test that!

  • Click on the "Normal usage test case” and drag/drop it onto "Negative start and end" and press OK to copy all elements of the test case. Then click on "Negative start and end." Most of the work is done for you!
  • Input: change "2" to "-2" in START_IN
  • Input: change "4" to "-4" in END_IN
  • For outcome, change value from "bcd" to "def" for the expected value.
  • Alternative: set the expected results value as an expression. Press […] to bring up the content of expected VAR CHAR window. Check the Evaluate  as an Expression checkbox,  then enter this value: SUBSTR ('abcdef', 4, 3) into the Single Value Expression field, and click OK.
  • You are done; the test case is now fully defined.

Boundary condition testing

These one-at-a-time, hand-crafted test cases are critical; there is no way for Quest Code Tester to figure out what your program will do automatically. There are, however, a whole class of test cases, usually referred to as "boundary condition" testing, which can be generated by Quest Code Tester for you, saving you lots of time.

For example, you want to make sure that when you provide a null value for STRING_IN, the function returns NULL, regardless of the inputs for START_IN, END_IN and INCLUSIVE_IN. Let's see how you can do that.

Use sets of values for inputs to generate multiple test cases for boundary conditions.

  • Click on the "Null string" test case.
  • Leave value for STRING_IN empty.
  • Click on the […] icon next to START_in and then press the radio group option labeled "Use an existing test data group."
  • Click on the numeric values folder, and you will then see a set of QCTO-defined (and even user-defined, if you created any) lists of numeric values.
  • Click on Typical Boundary Conditions for Integ... and press the OK button.
  • Do the same thing for END_IN. You now have multiple values for two arguments, so you will now tell Quest Code Tester that you want it to generate test cases for permutations of these values by choosing that option in the Step 2 header.
  • Next, change the outcome for this test. In this case, we don't want to see if the resulting string is equal to something else. It should be NULL. Click the Operator field and select "evaluates to NULL" from the list.  
  • You are now done; the test case is fully defined; all of the permutations will now be generated each time you run the test. And if you change the values in the Typical Boundary Conditions group (through the Test Data Manager available off the Dashboard Tools menu), those new values will be applied with the next run of the test.

Source code of program tested: Compile this code in your schema so that you can build your test definition for it.

CREATE OR REPLACE FUNCTION qctod#betwnstr (
   string_in IN VARCHAR2
 , start_in IN PLS_INTEGER
 , end_in IN PLS_INTEGER
 , inclusive_in IN BOOLEAN := TRUE
)
   RETURN VARCHAR2
IS
   v_start PLS_INTEGER;
   v_numchars PLS_INTEGER;
BEGIN
   IF    string_in IS NULL
      OR (start_in < 0 AND end_in > 0)
      OR (start_in > 0 AND end_in < 0)
      OR (start_in < 0 AND end_in > start_in)
      OR (start_in > 0 AND end_in < start_in)
   THEN
      RETURN NULL;
   ELSE
      IF start_in < 0
      THEN
         v_numchars := ABS (end_in) - ABS (start_in) + 1;
         v_start := GREATEST (end_in, -1 * LENGTH (string_in));
      ELSIF start_in = 0
      THEN
         v_start := 1;
         v_numchars := ABS (end_in) - ABS (v_start) + 1;
      ELSE
         v_start := start_in;
         v_numchars := ABS (end_in) - ABS (v_start) + 1;
      END IF;

      IF NOT NVL (inclusive_in, FALSE)
      THEN
         v_start := v_start + 1;
         v_numchars := v_numchars - 2;
      END IF;

      RETURN (SUBSTR (string_in, v_start, v_numchars));
   END IF;
END qctod#betwnstr;
/