X++ FormAdaptors – A Simple Example
My last post introduced a testability feature in the new AX called FormAdaptors. That post described changes in the product architecture that enabled FormAdaptors and why they have been so valuable for our internal automated regression testing strategy. In summary, FormAdaptors provide an API to interact with forms from X++ and run server side tests that are fast and reliable.
This post provldes a simple example of FormAdaptors so you can get a feel for the API. The form that we’re going to be targeting is the VendParameters form. We’re specifically going to interact with the two controls in the red and green boxes in the screenshot of the form shown below.
The scenario that we want to test is to verify that the green box control gets enabled and defaulted to false whenever the red box control is set to ‘Yes’. The red box control is the InvoiceMatching_UseInvoiceMatching control. The green box control is the InvoiceMatching_UseTotalPriceMatching control.
The X++ test code shown below implements the test scenario.
/// <summary>
/// Tests Invoice totals matching field settings
/// </summary>
[SysTestMethod]
public void InvoiceMatching_TotalsFieldSettings()
{
using (VendParametersFormAdaptor vendParameters = VendParametersFormAdaptor::open())
{
vendParameters.InvoiceMatching_UseInvoiceMatching().setValue(true);
vendParameters.InvoiceMatching_UseTotalPriceMatching().validateEnabled(true);
vendParameters.InvoiceMatching_UseTotalPriceMatching().validate(false);
}
}
The goal for this API is that the test is self explanatory when read… hopefully that is true for you! A few notes on this sample follow:
- [SysTestMethod] identifies the X++ method as a test method.
- Each form has a FormAdaptor class associated with it named <FormName>FormAdaptor. The class has multiple static constructors on it, one of which is the open() method shown.
- The FormAdaptor is wrapped in a using statement so the class is properly disposed after use.
- Chaining calls together is how you initiate actions on the form. For example, setValue() is a method on a CheckBoxControl.
- Convenience calls such as validateEnabled() interact with SysTest methods to assert failures and log additional information to aid in debugging failures.
Because this test is running on the server, there is no actual visualization of the test running. This is one disadvantage of executing form tests in this manner and was an initial concern for engineers on the team. This quickly went away when they saw how easy it was to debug the tests in addition to the benefits outlined in the previous post.