Acceptance Test Libraries (#ATL) for Dynamics 365 for Finance and Operations
One of the most exciting announcements in recent months (and that’s saying something, with how fast we move after OneVersion) for Microsoft Dynamics 365 for Finance and Operations developers is the ATL. This is the library that the product team uses to develop their own (unit or, better, integration) functional tests.
The Unit Testing framework has existed for a while in Dynamics AX, but it was complicated to use due to the complexity of maintaining the data needed to run the tests and allowing the creation of deterministic tests.
This library was released in PU27, although only a small part. In PU28, which is currently in the preview program, many more classes and some examples have been released, which I will take a look at here to see what we’re talking about.
The documentation is at the following link. For now, there is a good theoretical introduction, although not many examples; I will update this post when things improve:
For now, I want to briefly comment on the examples published in the PU28 preview:

As I said, the main problem with developing integration tests (functional tests by code) in previous versions was how disproportionately complex it was to maintain the test suite. What happens if we can run deterministic tests in practically any environment? Well, that would improve things quite a bit. What if I also have hundreds of helper classes to create this data and check the results? Well, I would have practically solved the whole problem, right?
Well, maybe not so much. But, for example, creating a sales order (with its items, inventory, customer, warehouses, …) in plain X++ would probably take us dozens or hundreds of lines of code. This is the code published in the first examples released this week:
// Create sales order line
var salesOrderLine = salesOrder.addLine() // Add a new line on the sales order
.setItem(item) // Using standard cost item
.setQuantity(SalesQuantity) // Set the sales quantity
.setInventDims([warehouse]) // Using default warehouse - site will be defaulted based on warehouse the same way as in the UI
.setPrice(UnitPrice) // Set the price
.setDeliverNow(PackingSlipQuantity) // Set the quantity that should be delivered
.save(); // Save the sales order line
This fluent syntax for creating the entities we need for the tests is possible thanks to the large number of classes included in this library that make these actions easier. In the original class, default values are created for secondary objects such as the item or the warehouse, as well as variables for the quantities (which we must then check in the next step).
Well, with this we create the order. But we want to check that the order is correct. This is a test, we’re here to check! No problem:
// Validate that we have one inventory transaction for the sales order line
salesOrder.lines().firstEntity().inventoryTransactions().assertExpectedLinesSet(AtlSpecifications::construct()
.addSpec(inventoryTransactions.spec() // Add one specification to the expected results
.withItem(item) // Item should be the same as on the sales order line
.withQty(-SalesQuantity) // The quantity should be the same as the sales quantity
.withStatusIssue(StatusIssue::OnOrder) // The status should be on order
.withInventDims([warehouse])) // The warehouse should be the same as on the sales order line
, 'Inventory transactions after creating the sales order.');
That’s how easy it is to validate that the previous action did what it was supposed to do (create customer transactions with the appropriate values). Easy, right?
I wanted to share this as an introduction to the library, but I’m sure I’ll be back here with more details and better examples. Tests are a fundamental part of the OneVersion strategy, and Test development will be key in the coming months for the success of projects.
I’ll also come back with the rest of the tools available for Testing in Finance and Operations. For now, you have a quick introduction in the video of my talk at the last Dynamics Saturday.