How to use test data in test and virtual services
Four ways to iterate over test data with Rational Integration Tester
The goal of using virtual services is to remove test dependencies and enable earlier testing. You can then build these techniques into a continuous delivery pipeline, thus ensuring each component is tested fully before delivery.
A virtual service is an emulation of an application or system. You can use this emulation in such a way that the system under test using the virtual service think that the life systems are still available. Implementing this technology enables the execution of tests earlier in the process and improves delivery velocity of higher-quality systems. IBM Rational® Integration Tester tests applications via their APIs and supports service virtualization by creating the virtual services.
This tutorial shows you four ways to use tests and virtual services to leverage test data with IBM Rational Integration Tester. Each example has distinct characteristics. Selecting the right implementation helps to reduce test and virtual service complexity, increase readability, and reduce maintenance.
This tutorial includes a sample project for download. The project is a web-based supermarket application that requests articles from a back-end system. The application requests a list of articles in one or more categories. A parameter accompanies each requested category and specifies the maximum number of articles to return. A price might accompany the article.
The sample project includes a virtual service, or stub, for a web service that selects a list of articles based on the requested category. The data is stored in a comma-separated text format (CSV) file. This tutorial explains how Rational Integration Tester uses this data file.
When developing tests and stubs in software projects:
Accompany each stub with tests
Create one (or more) tests to validate the correct operation of a stub. Experience shows that the combination of testing and stubbing can deliver high-quality test artifacts. Make sure you name the tests and stubs clearly and logically. Don't make the testers and developers guess.
Include log actions in the test and stubs
When tests and stubs run in Rational Integration Tester, trace information appears in the Test Lab console. If the test or stub contains log actions, the output is displayed in the console; log actions can also write to a file (via the use of a variable called a tag). Log actions help enhance readability and guide the tester or developer in the flow of execution of a test or stub. You can also log actual values of tags during execution.
Same input results, same output
To reduce complexity, business logic might be distributed across multiple variants of a stub. When possible, keep the overlapping behavior the same. Consider the following growth of stub logic:
- HardCoded: Return category Coffee with two items, all hard-coded.
- SingleCategory_DataFile: Return requested category with all items from the data file.
- MultiCategory_DataFile: Return multiple categories with a number of items from the data file.
When a single test requests the category Coffee, the virtual service should respond in the same way whether HardCoded, SingleCategory_DataFile, or MultiCategory_DataFile. It doesn't matter which stub is active; that test passes. This is an easy test to use to validate whether a stub is up and active.
Use more stringent tests to accompany the stubs when validating the specific logic. A request with multiple categories will pass on MultiCategory_DataFile but might fail on the other implementations of virtual service.
This tutorial highlights four methods to iterate over and process test data. Selecting the right implementation helps to reduce test and virtual service complexity, increase readability, and reduce maintenance. The four methods are:
- Hard-coding data
External test data
- Fetching test data
- Giving all category articles
Maximizing returned list
Business view and technical view
- Repeating on input, repeating on output
Return articles with price unavailable
1 - Hard-coding data
The hard-coded implementation is simple, quick to create, and you can enhance it later.
A simple stub will suffice when you make assumptions on the request. For example, the client application requests only Coffee articles. The service provides only a fixed response.
To create the simple hard coded stub, you can opt to create a stub from the message exchange pattern (MEP). This will create a skeleton stub without any data. It's easy to add data to the request and response messages after the empty skeleton stub is created. This is called hard-coded because the data is embedded in the message structure and inside the project, instead of stored outside the project (for example, in a file on disk or in a database).
You can also create a test based on the message exchange pattern. It will automatically create an test with a basic request and reply messages. You'll only need to fill in the category Coffee; there's no need to bother with the reply message. When you start the stub and run the test, the test fails. You can quickly update the response with the received message.
At this point, the developer/tester can test the application using this stub. There is the limitation that the application under test can request only for Coffee.
External test data
External test data separates data from test/stub logic. This enables altering the behavior of tests/stubs by altering the test data only. It also provides options such as sharing the test data across multiple tests/stubs.
To support a more flexible response, create a table that groups the articles within categories and adds details such as inventory and price. The imported test data in the preview is shown in the figure below.
Imported test data (preview)
All provided stubs in the sample project share the same test data. Use the Copy column names to clipboard button to quickly create new tags (variables) in a new stub. Additionally, because the same names are used between columns and tags, a reference to the test data automatically maps the data from the columns to the tags – this is very handy when you have more than just the five columns shown in this sample.
2 - Fetching test data
Fetching a single row of data returns a single row of data and can be used within a loop to retrieve multiple rows of data.
It is easy to fetch the first test data row with the Fetch Test Data action. You can then use that data in the response message of the stub. The data is then mapped to tags (variables). Normally, this action is used in a loop to iterate over the test data.
The Fetch Test Data action mapping columns to tags
Because only one row of test data is read, the tags have simple values (not a list). Add the tags containing the data in the Send Reply action.
The Send Reply action showing the reply message with the tags
It's wise to use the context menu (accessible via right-click of the mouse) to place the tags into the fields. This eliminates errors in typing the text.
3 - Giving all category articles
The Lookup Test Data action is used to select multiple rows from test data in one step. This action maintains the simple structure in the test/stub.
The next implementation of the virtual service is to respond on the requesting category. The reply will give all articles of a category. This is implemented with the Lookup Test Data action. In the stub definition in the received request message, the category is stored in the tag %%filterCategory%%. Use this tag to filter the test data (Config tab > Lookup values).
Filtering data with a tag
The received data is a list of zero or more articles. Each column is stored into tags that can store multiple values (list tags).
Mapping selected rows mapped to appropriate tags
Rational Integration Tester automatically creates a response message based on the number of elements found in the list tags. You only need to specify that the article node in the reply message is repeating (using the contextual menu). This is visible by the red marker icon and green line in the figure below.
Marking the article node as repeating
The Lookup Test Data action can be powerful when the selection is done with one or more variables. The structure of the stub is also simple.
Maximizing the returned list
Use the Iterate Over Test Data action to fetch a row of data and process it directly.
In the previous example, all test data that satisfied the selection criteria was selected. That might be thousands of articles. But, what if you want only the first 10? To accomplish this, enhance the previous approach and remove any elements from the list above the number requested. That might result in fetching thousands of articles and deleting most of them.
There is another approach. Assume that only one category is requested. This value is stored in the appropriate tag (filterCategory) on the Input tab of the stub.
The logic of the stub is to iterate over test data with a filter applied. This fetches one row of test data matching the filter criteria and eliminates the need to apply separate logic for filtering.
Filtering in the Iterate Test Data action results
The Iterate Test Data action returns a single row of test data. It cannot return lists of values. The tags populated with the test data are simple values. If the collection lists (Java™ type ArrayList() ) is not yet holding maximum number of entries, you can add the values to the lists. The decision is shown in a Business View representation in the figure below.
The code to add the retrieved article to the collection lists is:
listArticle.add(tags["Article"]); listPrice.add(tags["Price"]); listStock.add(tags["Stock"]); tags["listSize"]=listArticle.size();
The above code is represented in the business view of the stub as Function:Add to List, shown in the figure below.
Stub logic shown in the Business View
Business View and Technical View
The tests and stubs can be represented in two ways: the Business View and the Technical View (). Normally, the Technical View is used and provides details of the actions used. When large snippets of code are used to embed business logic, it can cloak the flow of the stub.
Showing the same stub in the technical view
To overcome this issue of getting an overview, you can switch to the Business View. This view provides the option to rename the actions in the test and stub. This option can dramatically improve the readability of the test and stub.
4 - Repeating on input, repeating on output
The previous example focused on the creation of the collection lists. Those lists were used in the reply message. This example lets you have multiple categories on the input as well.
On the input tab, the repetitive node must be marked as repeating. Within that node, the mapping of the field to the tag is defined. Enhance the mapping (Store tab) with the Append to list of values so that a single store results in a tag containing the list of categories to filter.
Use the Append to list of values to return lists of filterCategories
From the input of the stub, there is now a list of requested categories and a list with the appropriate maximum number of returned items. Iterate over this list using an Iterate While action. For each category, use the previously created Iterate Test Data to fetch rows of test data for that category. When the lists do not reach their maximum, the data is stored in the resulting lists.
Complex logic of fetching test data in the Business View
Returning articles with price unavailable
Each article might have a price in the test data file. If the price is available, it's processed the same as described above. An initial data file could assign all articles a price. But if the price is not available, the XML node should not appear in the reply message. Some additional logic is needed in the virtual service.
The above behavior can be implemented by setting those values to null as is done in the following ECMAScript logic. The removal of the XML node is automatic.
Note: Nothing changes in the Send Reply message. Depending on the provided data, it adapts automatically.
Adding a null value when price information is not available
Conclusion and recommendations
Rational Integration Tester gives the flexibility to create simple or complex virtual services. Both are of value in a test environment. Rational Integration Tester has several options for using test data. You can choose the best fit for your situation.
The unique combination of testing and stubbing in one tool helps deliver quality test assets.
When assumptions are made on the behavior of the virtual service, you can limit the complexity of the virtual service. This affects creation time and maintenance. When variants of the same virtual services are using the same (hard-coded) test data, the tests and stubs might be upward-compatible. The test for the simple stub can be reused for the complex stubs.
- Download a trial of Rational Integration Tester Starter Edition
- Rational Integration Tester knowledge center
- Continuous Testing learning circle
- Download Rational Integration Tester
- Service Virtualization for Dummies eBook
- Service virtualization
- Solve real problems quickly with journeys on developer.ibm.com/code