Mainframe Test Scripting Made Easy Using Test4z

Hizir Cagin Bektas
5 min readJan 31, 2022

--

Automating tests can be challenging for mainframe teams. Test4z, announced recently, makes test automation easy by enabling any language or test framework to consume its web-based REST APIs.

In this article, we are going to learn about Test4z by creating a sample test suite. We need just a little Mainframe knowledge as well as any programming language. You will gain an understanding of Test4z and how to write Mainframe batch application tests using your favorite programming language and your favorite IDE!

Test4z provides a set of REST APIs for accessing, querying, copying and updating mainframe datasets. A sample code repository, which is publicly available on Github and is open source, is available!

The sample repository contains a data set, a copybook and a batch application which is used in the sample test suites. A Zowe powered automation script helps to upload test data sets to the mainframe.

Let’s get into testing our batch application. Here is the use case:

  • A batch application updates the Notification-Date field of the records (customers) who met certain criteria.

During the test creation process, I will be using VS Code IDE and node.js, npm, TypeScript, Jest tech stack. The tech stack is up to you since Test4z provides REST APIs that you can access by using any programming language. Before we start I am assuming that all the Test4z installations and configurations are done on the Mainframe and the client side.

I will be extending the existing Test4z Sample repository instead of creating it from scratch.

Here is the folder structure of the sample repository:

Each directory contains a sample test for a certain feature and they are using the same use case. Let’s add one more directory and call it “example” then create a test file named example.test.ts.

There is a Test4z node package available on npmjs.com to make things even easier! All the required models, http client, and testing helpers are there for developers to use.

Let’s get back to the example.test.ts. First, import the Test4z node package,

import { Test4zService } from “@broadcom/test4z”;

then we will need some variable definitions for the data sets and batch application that we want to test.

const mainDataset = “HLQ.TEST4Z.BATCHAPP.CUSTIN”;
const backupDataset = “HLQ.TEST4Z.BATCHAPP.CNBACKUP”;
const myBatchApp = “HLQ.TEST4Z.BATCHAPP.JCL(CUSTSEQ)”;

Better take a backup to be able roll the data back which will be affected by the batch application. To achieve this, we can use the Test4z Snapshot feature. It will simply create a backup of the given input data set.

//Take a backup from the main data set
const snapshotResult =
await Test4zService.takeSnapShot(mainDataset, backupDataset);
//Verify the API Request was successful
expect(snapshotResult).toBeSuccessfulResult();

It is time to submit the batch application and change some values in the customer dataset! Test4z does not currently provide any job submission support. Instead, we use Zowe SDK’s JobSubmit feature. Note, even though we use Zowe for the job submission, there is a method in the Test4z node package to submit the job and get the job return code back.

//Execute Batch Application to modify the main data set as expected //in the use caseconst job = 
await Test4zService.submitJobUsingDataset(myBatchApp);
//Verify the BatchApp JCL executed successfully
expect(job).toBeSuccessful();

We are expecting some changes in the main data set now. Here we can use the backup data set to compare, since it is not affected by any changes. Test4z Compare comes into the picture right here. It allows us to compare 2 data sets and get a very comprehensive result to use in the assertions.

//Compare the mainDataset with the copyDataset to identify the //changes.const compareResult =
await Test4zService.compare(backupDataset, mainDataset);
//Verify the API Request was successful
expect(compareResult).toBeSuccessfulResult();
//Asserting the compare result summary
expect(compareResult.data.summary.oldRecordsProcessed).toBe(75);
expect(compareResult.data.summary.newRecordsProcessed).toBe(75);
expect(compareResult.data.summary.insertedLines).toBe(0);
expect(compareResult.data.summary.changedLines).toBe(24);
expect(compareResult.data.summary.matchedLines).toBe(51);
expect(compareResult.data.summary.deletedLines).toBe(0);

Now it’s time to roll back to the backup data set, so our main data set will revert to its original state just like before this test suite ran.

//Roll-back to the main dataset, using the backup datasetconst backupResult =
await Test4zService.rollbackDataSet(backupDataset, mainDataset);
//Verify the API Request was successful
expect(backupResult).toBeSuccessfulResult();

To wrap up all the code snippets above, our example.test.ts should look like this:

import { Test4zService } from “@broadcom/test4z”;const mainDataset = “HLQ.TEST4Z.BATCHAPP.CUSTIN”;
const backupDataset = “HLQ.TEST4Z.BATCHAPP.CNBACKUP”;
const myBatchApp = “HLQ.TEST4Z.BATCHAPP.JCL(CUSTSEQ)”;
describe(“Example Test4z test suite for Medium.com article”, function () {
beforeEach(async () => {
//Take a backup from the main dataset.
const snapshotResult =
await Test4zService.takeSnapShot(mainDataset, backupDataset);
//Verify the API Request was successful
expect(snapshotResult).toBeSuccessfulResult();
});
test(“Customer notification batch app test”, async function () {
//Execute Batch Application to modify the main dataset as
//expected in the use case
const job =
await Test4zService.submitJobUsingDataset(myBatchApp);
//Verify BatchApp JCL executed successfully
expect(job).toBeSuccessful();
//Compare the mainDataset with the copyDataset to identify any
//changes.
const compareResult =
await Test4zService.compare(backupDataset,mainDataset);
//Verify the API Request was successful
expect(compareResult).toBeSuccessfulResult();
//Asserting the compare result summary
expect(compareResult.data.summary.oldRecordsProcessed).toBe(75);
expect(compareResult.data.summary.newRecordsProcessed).toBe(75);
expect(compareResult.data.summary.insertedLines).toBe(0);
expect(compareResult.data.summary.changedLines).toBe(24);
expect(compareResult.data.summary.matchedLines).toBe(51);
expect(compareResult.data.summary.deletedLines).toBe(0);
});
afterEach(async () => {
//Roll-back the main data set, using the backup data set
const backupResult =
await Test4zService.rollbackDataSet(backupDataset, mainDataset);

//Verify the API Request was successful
expect(backupResult).toBeSuccessfulResult();
});
});

Let’s run the test suite by executing the following command:

npm run test example.test.ts

Yey! Our test suite proves that the batch application works as expected. I like when it’s all green! So now we may tie this test suite to our CI/CD pipeline to run it automatically.

--

--