Tuesday, January 20, 2009

Testing Level - Unit Testing

1) Unit Testing

"Unit testing is done for each module of the program to ensure the validity of each module. This type of testing is done usually by developers by writing test cases for each scenarios of the module and writing the results occurring in each step for each module. "

"If one performs testing on a unit then that level of testing is known as unit level testing. It is white box testing usually developers perform it.
Unit: -It is defined as a smallest part of an application."

"Unit testing is the process of testing a particular complied program, i.e., a window, a report, an interface, etc. independently as a stand-alone component/program. The types and degrees of unit tests can vary among modified and newly created programs. Unit testing is mostly performed by the programmers who are also responsible for the creation of the necessary unit test data. "

This is a typical scenario of Manual Unit Testing activity-

A Unit is allocated to a Programmer for programming. Programmer has to use ‘Functional Specifications’ document as input for his work.

Programmer prepares ‘Program Specifications’ for his Unit from the Functional Specifications. Program Specifications describe the programming approach, coding tips for the Unit’s coding.

Using these ‘Program specifications’ as input, Programmer prepares ‘Unit Test Cases’ document for that particular Unit. A ‘Unit Test Cases Checklist’ may be used to check the completeness of Unit Test Cases document.

‘Program Specifications’ and ‘Unit Test Cases’ are reviewed and approved by Quality Assurance Analyst or by peer programmer.

The programmer implements some functionality for the system to be developed. The same is tested by referring the unit test cases. While testing that functionality if any defects have been found, they are recorded using the defect logging tool whichever is applicable. The programmer fixes the bugs found and tests the same for any errors.


Stubs and Drivers

A software application is made up of a number of ‘Units’, where output of one ‘Unit’ goes as an ‘Input’ of another Unit. e.g. A ‘Sales Order Printing’ program takes a ‘Sales Order’ as an input, which is actually an output of ‘Sales Order Creation’ program.

Due to such interfaces, independent testing of a Unit becomes impossible. But that is what we want to do; we want to test a Unit in isolation! So here we use ‘Stub’ and ‘Driver.

A ‘Driver’ is a piece of software that drives (invokes) the Unit being tested. A driver creates necessary ‘Inputs’ required for the Unit and then invokes the Unit.

A Unit may reference another Unit in its logic. A ‘Stub’ takes place of such subordinate unit during the Unit Testing. A ‘Stub’ is a piece of software that works similar to a unit which is referenced by the Unit being tested, but it is much simpler that the actual unit. A Stub works as a ‘Stand-in’ for the subordinate unit and provides the minimum required behavior for that unit.

Programmer needs to create such ‘Drivers’ and ‘Stubs’ for carrying out Unit Testing.

Both the Driver and the Stub are kept at a minimum level of complexity, so that they do not induce any errors while testing the Unit in question.

Example - For Unit Testing of ‘Sales Order Printing’ program, a ‘Driver’ program will have the code which will create Sales Order records using hard coded data and then call ‘Sales Order Printing’ program. Suppose this printing program uses another unit which calculates Sales discounts by some complex calculations. Then call to this unit will be replaced by a ‘Stub’, which will simply return fix discount data.

Unit Test Cases

It must be clear by now that preparing Unit Test Cases document (referred to as UTC hereafter) is an important task in Unit Testing activity. Having an UTC, which is complete with every possible test case, leads to complete Unit Testing and thus gives an assurance of defect-free Unit at the end of Unit Testing stage. So let us discuss about how to prepare a UTC.

Think of following aspects while preparing Unit Test Cases –

v Expected Functionality: Write test cases against each functionality that is expected to be provided from the Unit being developed.

e.g. If an SQL script contains commands for creating one table and altering another table then test cases should be written for testing creation of one table and alteration of another.

It is important that User Requirements should be traceable to Functional Specifications, Functional Specifications be traceable to Program Specifications and Program Specifications be traceable to Unit Test Cases. Maintaining such traceability ensures that the application fulfills User Requirements.

v Input values:

o Every input value: Write test cases for each of the inputs accepted by the Unit.

E.g. If a Data Entry Form has 10 fields on it, write test cases for all 10 fields.

o Validation of input: Every input has certain validation rule associated with it. Write test cases to validate this rule. Also, there can be cross-field validations in which one field is enabled depending upon input of another field. Test cases for these should not be missed.

E.g. A combo box or list box has a valid set of values associated with it.

A numeric field may accept only positive values.

An email address field must have ampersand (@) and period (.) in it.

A ‘Sales tax code’ entered by user must belong to the ‘State’ specified by the user.

o Boundary conditions: Inputs often have minimum and maximum possible values. Do not forget to write test cases for them.

e.g. A field that accepts ‘percentage’ on a Data Entry Form should be able to accept inputs only from 1 to 100.

o Limitations of data types: Variables that hold the data have their value limits depending upon their data types. In case of computed fields, it is very important to write cases to arrive at an upper limit value of the variables.

o Computations: If any calculations are involved in the processing, write test cases to check the arithmetic expressions with all possible combinations of values.

v Output values: Write test cases to generate scenarios, which will produce all types of output values that are expected from the Unit.

e.g. A Report can display one set of data if user chooses a particular option and another set of data if user chooses a different option. Write test cases to check each of these outputs. When the output is a result of some calculations being performed or some formulae being used, then approximations play a major role and must be checked.

v Screen / Report Layout: Screen Layout or web page layout and Report layout must be tested against the requirements. It should not happen that the screen or the report looks beautiful and perfect, but user wanted something entirely different! It should ensure that pages and screens are consistent.

v Path coverage: A Unit may have conditional processing which results in various paths the control can traverse through. Test case must be written for each of these paths.

v Assumptions: A Unit may assume certain things for it to function. For example, a Unit may need a database to be open. Then test case must be written to check that the Unit reports error if such assumptions are not met.

v Transactions: In case of database applications, it is important to make sure that transactions are properly designed and no way inconsistent data gets saved in the database.

v Abnormal terminations: Behavior of the Unit in case of abnormal termination should be tested.

v Error messages: Error messages should be short, precise and self-explanatory. They should be properly phrased and should be free of grammatical mistakes.

UTC Document

Given below is a simple format for UTC document.

Test Case No.

Test Case purpose

Procedure

Expected Result

Actual result

ID which can be referred to in other documents like ‘Traceability Matrix’, Root Cause Analysis of Defects etc.

What to test

How to test

What should happen

What actually happened?

This column can be omitted when Defect Recording Tool is used.

Note that as this is a sample, we have not provided columns for Pass/Fail and Remarks.

Example:

Let us say we want to write UTC for a Data Entry Form below:

ITEM MASTER FORM


Item Number : ------------------------------


Item Name: ------------------------------


Item Price : --------------------------------


Given below are some of the Unit Test Cases for the above Form:

Test Case No.

Test Case purpose

Procedure

Expected Result

Actual result

1

Item no. to start by ‘A’ or ‘B’.

1.Create a new record.

2.Type Item no. starting with ‘A’.

3.Type item no. starting with ‘B’.

4.Type item no. starting with any character other than ‘A’ and ‘B’.

2,3. Should get accepted and control should move to next field.

4. Should not get accepted. An error message should be displayed and control should remain in Item no. field.

2.

Item Price to be between 1000 to 2000 if Item no. starts with ‘A’.

1.Create a new record with Item no. starting with ‘A’.

2.Specify price <>

3.Specify price >2000.

4.Specify price = 1000.

5.Specify price = 2000.

6.Specify price between 1000 and 2000.

2,3.Error should get displayed and control should remain in Price field.

4,5,6.Should get accepted and control should move to next field.

UTC Checklist

UTC checklist may be used while reviewing the UTC prepared by the programmer. As any other checklist, it contains a list of questions, which can be answered as either a ‘Yes’ or a ‘No’. The ‘Aspects’ list given in Section 4.3 above can be referred to while preparing UTC checklist.

e.g. Given below are some of the checkpoints in UTC checklist –

  1. Are test cases present for all form field validations?
  2. Are boundary conditions considered?
  3. Are Error messages properly phrased?

Defect Recording

Defect Recording can be done on the same document of UTC, in the column of ‘Expected Results’. This column can be duplicated for the next iterations of Unit Testing.

Defect Recording can also be done using some tools like Bugzilla, in which defects are stored in the database.

Defect Recording needs to be done with care. It should be able to indicate the problem in clear, unambiguous manner, and reproducing of the defects should be easily possible from the defect information.

Conclusion

Exhaustive Unit Testing filters out the defects at an early stage in the Development Life Cycle. It proves to be cost effective and improves Quality of the Software before the smaller pieces are put together to form an application as a whole. Unit Testing should be done sincerely and meticulously, the efforts are paid well in the long run.

No comments:

Post a Comment