5

Dynamics AX 2012 comes with unit testing support.

To have meaningful tests some test data needs to be provided (stored in tables in the database).

To get a reproducable outcome of the unit tests we need to have the same data stored in the tables every time the tests are run. Now the question is, how can we accomplish this?

I learned that there is the possibility of setting the isolation level for the TestSuite to SysTestSuiteCompanyIsolateClass. This will create an empty company and delete the company after the tests have been run. In the setup() method I can fill my testdata into the tables with insert statements. This works fine for small scenarios but becomes cumbersome very fast if you have a real life project.

I was wondering if there is anyone out there with a practical solution of how to use the X++ Unit Test Framework in a real world scenario. Any input is very much appreciated.

elToro
  • 946
  • 8
  • 28
  • While I'm very interested in your question, the scope is fairly broad. It would be helpful if you could provide a specific example where you encountered problems in writing the unit test. – FH-Inway Sep 10 '15 at 12:26
  • There is no specific problem at the moment, I'm just starting with AX and was wondering of how to tackle to topic on consistent testdata leading to reproducable testing results. Your answer below therefore was very helpful. – elToro Sep 10 '15 at 12:59

4 Answers4

6

I agree that creating test data in a new and empty company only works for fairly trivial scenarios or scenarios where you implemented the whole data structure yourself. But as soon as existing data structures are needed, this approach can become very time consuming.

One approach that worked well for me in the past is to run unit tests in a existing company that already has most of the configuration data (e.g. financial setup, inventory setup, ...) needed to run the test. The test itself runs in a ttsBegin - ttsAbort block so that the unit test does not actually create any data.

Another approach is to implement data provider methods that are test agnostic, but create data that is often used in unit tests (e.g. a method that creates a product). It takes some time to create a useful set of data provider methods, but once they exist, writing unit tests becomes a lot faster. See SysTest part V.: Test execution (results, runners and listeners) on how Microsoft uses a similar approach (or at least they used to back in 2007 for AX 4.0).

Both approaches can also be combined, you would call the data provider methods inside the ttsBegin - ttsAbort block to create the needed data only for the unit test.

Another useful method is to use doInsert or doUpdate to create your test data, especially if you are only interested in a few fields and do not need to create a completely valid record.

FH-Inway
  • 3,766
  • 1
  • 17
  • 35
4

I think that the unit test framework was an afterthought. In order to really use it, Microsoft would have needed to provide unit test classes, then when you customize their code, you also customize their unit tests.

So without that, you're essentially left coding unit tests that try and encompass base code along with your modifications, which is a huge task.

Where I think you can actually use it is around isolated customizations that perform some function, and aren't heavily built on base code. And also with customizations that are integrations with external systems.

Alex Kwitny
  • 10,154
  • 2
  • 41
  • 66
  • +1 for the huge task of writing unit tests for base code. Microsoft admits that fact, but so far has been unwilling to release any of their unit tests. The discussions in [SysTestQuickStart](http://blogs.msdn.com/b/dpokluda/archive/2006/08/25/724280.aspx) and [Using the SysTest unit testing framework in Dynamics AX – why bother?](http://blogs.msdn.com/b/dave_froslie/archive/2011/07/26/using-the-systest-unit-testing-framework-in-dynamics-ax-why-bother.aspx) list some reasons for that. – FH-Inway Sep 11 '15 at 08:27
  • 1
    I'd imagine they don't want to release their unit tests because they don't want them to be heavily criticized. AX has organically grown for years, so I'd imagine the unit tests would make me sad. – Alex Kwitny Sep 11 '15 at 15:34
3

Well, from my point of view, you will not be able to leverage more than what you pointed from the standard framework. What you can do is more around release management. You can setup an integration environment with the targeted data and push your nightbuild model into this environmnet at the end of the build process and then run your tests. Yes, it will need more effort to set it up and to maintain but it's the only solution I've seen untill now to have a large and consistent set of data to run unit or integration tests on.

Geoffrey DELMEE
  • 772
  • 4
  • 8
  • I was also thinking along those lines. Am I correct assuming that with "integration environment" you mean a test environment? So we are talking about Continous Delivery and automating the build and deployment process. Could you point me in the right direction of which tools to use to accomplish this kind of automation. Thx. – elToro Sep 10 '15 at 13:02
  • 1
    Take a look at [Dynamics AX Build Scripts](https://dynamicsaxbuild.codeplex.com/) and [Dynamics AX TeamCity Build Automation](https://daxteamcityautomation.codeplex.com/). – FH-Inway Sep 10 '15 at 13:44
  • 1
    For integration environment, yes it's a test environment. I call it as is because it is for integration tests, not for user tests. You can also take a look at this link: http://blogs.msdn.com/b/axsa/archive/2012/10/22/tfs-integration-with-microsoft-dynamics-ax-2012-and-automated-scripts-for-build-and-deployment.aspx You'll find references on TFS white paper and MS build script examples in PowerShell to run a build. Im ade my own scripts following the same steps in batch file as I'm not PowerShell fluent :) Then you ca link to deployment scripts to directly deliver to the taget environment. – Geoffrey DELMEE Sep 10 '15 at 14:46
  • Thx FH-Inway and Geoffrey DELMEE. These links are extremely helpful and will help me to build an automated continous delivery process. – elToro Sep 11 '15 at 06:19
0

To have meaningful tests some test data needs to be provided (stored in tables in the database).

As someone else already indicated - I found it best to leverage an existing company for data. In my case, several existing companies.

To get a reproducable outcome of the unit tests we need to have the same data stored in the tables every time the tests are run. Now the question is, how can we accomplish this?

We have built test helpers, that help us "run the test", automating what a person would do - give you have architeced your application to be testable. In essence our test class uses the helpers to run the test, then provides most of the value in validating the data it created.

I learned that there is the possibility of setting the isolation level for the TestSuite to SysTestSuiteCompanyIsolateClass. This will create an empty company and delete the company after the tests have been run. In the setup() method I can fill my testdata into the tables with insert statements. This works fine for small scenarios but becomes cumbersome very fast if you have a real life project.

I did not find this practical in our situation, so we haven't leveraged it.

I was wondering if there is anyone out there with a practical solution of how to use the X++ Unit Test Framework in a real world scenario. Any input is very much appreciated.

We've been using the testing framework as stated above and it has been working for us. the key is to find the correct scenarios to test, also provides a good foundation for writing testable classes.

Pang
  • 8,605
  • 144
  • 77
  • 113