Monday, May 4, 2009

Unit Testing

Unit Testing

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 hardcoded 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.

 

No comments:

Post a Comment