Automating Tests for Batch Applications

I’ve had numerous questions on how to automate testing batch programs. In some places these are also termed host programs, since the batch runs on a mainframe host. Let’s take a look at an example on how to do this.

A Little History

You may have seen in old movies, pictures of computers with large tape drives spinning. In those old days, data was kept on magnetic tapes. One of the common rules with using tape for storage is that you did not overwrite data on the same tape. One set of tapes was used for input to the program; another set of tapes was used as output for the program. For example, one input tape might contain all the customer records and another input tape would contain all the transactions against those records. The output tape would be written with the updated customer records.

Looking at this from the viewpoint of modern functional languages, the programs used an immutable set of input data. Testing these programs was fairly simple (although a little expensive due to the relatively high cost of computer power in those days). You ran the program and checked the output. If the output was not correct, you fixed the program and ran it again until the output was correct.

Example Test

Using the Given-When-Then syntax, a test for a batch program might look like the following. The amount of data in a customer record or transaction can be larger, but the flow will be the same.

Given customer record is:
Name Phone Number Other Information …
Sam 919-555-1212
And transaction record to add a new number is:
Name New Phone Number
Sam 919-999-9999
When the transactions are processed Then customer record should be:
Name Phone Number Other Information …
Sam 919-999-9999

Each of the tables represents the contents of one of the input or output files.

Database Issues

There are still many batch programs that follow this same model with the exception that the files are kept on disk, rather than tape. However, many modern batch programs update a database, typically an enterprise-wide database. In programming terms, the database is mutable (changeable), which makes testing more complicated. If one is going to run a test over, the database needs be restored to the condition that existed prior to running the program.

In essence, you need to make

Name Phone Number Other Information …
Sam 919-999-9999

go back to

 
Name Phone Number Other Information …
Sam 919-555-1212

There are many ways to make the database reusable. Which way to choose is dependent on your execution environment. Here are some of the options:

  • Restore the original database records from a backup after running the test. You save just the original records that will be affected by the test and load them after the test. You could restore the full database by a restore command or a virtual machine reboot. For enterprise solutions, there are products on the market for managing this test data.
  • Put the changes into an SQL transaction, but do not commit the transaction. This can work, but also has issues with potentially conflicting commits.
  • If the database records are accessed via a service (web, REST, etc.), create a test double for that service which provides the original records and checks that updated records have the desired data. You can use handcrafted test doubles or service virtualization.
  • If the database records are accessed via SQL commands or stored procedures, isolate all those accesses in subroutines. Then create subroutines that return the input records and check that updates have the correct data. These subroutines are often called mocks. The set of subroutines that access the real data can be tested separately to ensure they work properly. Both the real data routines and the mock data routines are reusable in other applications.

Other Details

  • Executing the application

The application is executed from the When clause:

When the transactions are processed 

The method corresponding to this clause needs to call the appropriate job control to setup and execute the application.

  • Transaction format

The format of a transaction can vary. It could be fixed column, comma delimited, XML, or some other format. To automated the test, a routine can convert the data from a table such as the following to the actual format. From a test documentation standpoint, it’s usually easier to read a table than to read the actual formatted data.

Name New Phone Number
Sam 919-999-9999

  • Checking transaction format

You could have tests that check the conversion of formatted data to data structures. An example of a conversion test is:

Given transaction input:
“Name=Sam,New Phone Number=919-999-9999 "
When converted 
Then it is interpreted as: 
Name New Phone Number
Sam 919-999-9999

Summary

The testing of batch applications can be automated. Handling database issues can be done either on an individual application basis, but it can be far more efficient to handle them with a common approach (test data manager or reusable mocks/test doubles).