Question
· Oct 30

Using the other unit testing frameworks with IPM?

I assume IPM manifest tag UnitTest is tightly coupled with the standard unit test framework, right? However we have our own one that predates the standard one and we are not going to switch.

I think I need to import the unit test cases and then be able to run a single class method for the test run. Any ideas how this would be possible?

Discussion (9)3
Log in or sign up to continue

I had a look into the IPM source code and I guess the correct places where the testing action happens are:

  • %ZPM.PackageManager.Developer.Processor.UnitTest (OnPhase method)
  • %ZPM.PackageManager.Developer.UnitTest.Manager

However I got a quite confused how I would be able to inject my own Processor.UnitTest and/or UnitTest.Manager there and what are those pParams that are passes everywhere.

Now I have this kind of workaround:

<!-- unit testing workaround -->
<Invoke Phase="Test" Class="Company.UnitTest.IPM" Method="Load" CheckStatus="true">
  <Arg>${root}/test</Arg>
</Invoke>
<Invoke Phase="Test" Class="Company.UnitTest.IPM" Method="RunTestPackage" CheckStatus="true">
  <Arg>CompanyTests</Arg>
</Invoke>
<Invoke Phase="Unconfigure" Class="%SYSTEM.OBJ" Method="DeletePackage" CheckStatus="true">
  <Arg>CompanyTests</Arg>
</Invoke>

The amount of boilerplate is tolerable.

Test cases are located in ${root}/test.

Company.UnitTest.IPM is just an IPM "compatible" facade for our framework.

Now I can run test -o my-company-module. This has been working fine so far, fingers crossed there is no nasty surprises just waiting around the corner ...

@Evgeny Shvarov to some extent we already do, via the -DUnitTest.ManagerClass parameter we use to run TestCoverage and through custom resource processors (which I see @Jani Hurskainen is already playing with!)

The common pattern in ObjectScript if you're going to customize unit test processes is to write a subclass of %UnitTest.Manager that does things the way you want. (And probably a few subclasses of %UnitTest.TestCase that add the standard assertion types, maybe some application-specific utility methods / wrappers, etc.) IPM will play well with this model, it's more work (all around!) if you want to write your own entire unit test framework from scratch.

@Jani Hurskainen providing a top-level answer here:

If you want to truly build your own unit test framework from scratch, you'd need to create a custom resource processor class in IPM. I see from https://github.com/intersystems/ipm/issues/616 that you've already discovered this feature and I appreciate your tenacity and the deep dive into IPM that you're doing.

Every development team I've worked on within InterSystems (that is, three very different ones) has had its own things it's wanted to do that %UnitTest.Manager and %UnitTest.TestCase don't *quite* do the way we want, with the API we want, right out of the box. The approach in general is to extend %UnitTest.Manager to tweak unit test runner behaviors (IPM does this itself, as you may have noticed); to extend %UnitTest.TestCase to add application-specific utility methods, assertions, and generic On(Before|After)(All|One)Test(s?) implementations (often controlled by class parameters); and potentially to add some mix-in utility classes that one might extend along with %UnitTest.TestCase or your own derived unit test base class.

For the basic case of "I want to run tests with my own %UnitTest.Manager subclass" we have a flag you can pass in to override the unit test manager class, -DUnitTest.ManagerClass=yourclassname. See https://community.intersystems.com/post/unit-tests-and-test-coverage-int... for an example of how to use this (with my team's https://github.com/intersystems/TestCoverage open source package).

At the IPM codebase level, there's special treatment of the common "pParams" array passed around everywhere - something looking at pParams("UnitTest","ManagerClass") will find the value specified in -DUnitTest.ManagerClass in the package manager shell command.

Hopefully this is helpful!