Skip to content

Good tests

Elwardi edited this page Nov 6, 2022 · 2 revisions

What makes a good test

Why write unit/integration tests

  • To make sure new functionality works as intended
  • To make sure further development does not introduce bugs, or change older behaviour (Unintentionally).
  • To better document the expected usage of your code.
  • To gauge performance of test units if needed.

What testable OpenFOAM code looks like

Typically; the presence of a mesh makes it extremely difficult to write generic tests. There are static and many dynamic mesh types - and your code might suffer bugs on specific cell shapes too.

To ease this up, I opted for a suite of small but diverse OpenFOAM cases to execute the tests on, where the meshes have all kinds of cell shapes.

Now, a good test needs the code it's testing to be "testable" first. Most classes in OpenFOAM are test-friendly, and if you want to make your classes play nice with the Unit Testing concept, you can follow a simple pattern while developing your code:

  • Always pass at least a mesh object and a dictionary (or an Istream) to your class's constructor.
    • Passing the mesh gives you access to the most important object database.
    • It also declares the mesh to be an external dependency of your class.
    • Passing a dictionary makes your class configurable from outside code
      • The caller is responsible for putting the dictionary together.
      • This removes the need to read from disk while unit-testing

What exactly should I test

  • Your first priority should be testing the public interface of your classes
    • You don't want the interface to change its behavior suddenly.
    • Start with the methods you think are most important.
  • If you depend on external libraries (OpenFOAM libs are external to you, if you don't have control over them), it might be a good idea to put some tests for public methods on the OpenFOAM side; just to make sure you're notified as soon as the OpenFOAM devs change the behavior of the methods you're critically using in your code.

A general rule of thumb: If you need to test a class's method, make it a public one. Otherwise, just skip unit-testing it.

  • Sometimes, there will be a need to test the behavior of private/protected methods of some classes in external libraries.
    • If you're in this unfortunate situation; some function pointers, friends static members with templating can help you hack up the class and steal its private members.
    • Include memberStealer.H from the deprecated version of the framework and use the macros defined there to gain access to the private methods/members you're after.

Code in memberStealer.H is not Standard-Compliant but it's safe and triggers no undefined behavior on all major compilers as far as I can tell.