Add optional message parameter to assertEquals

663 Views Asked by At

Disclaimer: I'm totally new to Haxe, but I have experience in many other languages.

I have tests similar to the following:

  function doTest(type:SomethingMagic, tests:Array<Array<Int>>) {
    for (t in tests) {
      var res = DoSomeMagicalWork(t[0], t[1], t[2], t[3], t[4], t[5], t[6], t[7]);
      assertEquals(type, res.type);
    }
  }

The problem with this is that the unit test framework, when run on many different arrays, doesn't give me the correct line for which the test failed. In other words, if I'm running this method with a bunch of arrays, like:

 doTest(SOME_MAGIC_TYPE,
    [[0, 0, 0, 1625, 0, 35, 0, 0, 0, 0, 0],
    ...
 ]);

and one of these lines fails, it doesn't tell me which line failed. Now, I know that I could probably restructure these tests to be a bit more intuitive anyway, but this was written by someone else, and I don't have the ability to change each of these at the moment.

What I'd like to do is the following:

  function doTest(type:SomethingMagic, tests:Array<Array<Int>>) {
    var number = 0;
    for (t in tests) {
      var res = DoSomeMagicalWork(t[0], t[1], t[2], t[3], t[4], t[5], t[6], t[7]);
      assertEquals(type, res.type, "Test #" + number + " for type " + type);
      number++;
    }
  }

So, basically, I'd like to be able to pass in some extra messaging information to the assertEquals function, similar to what one can do in other unit testing frameworks. Then, upon failure, it would output the standard assertion message, possibly appended by the additional message I sent as a parameter to the function. Originally, I thought it was as simple as sub-classing haxe.TestCase, but that doesn't appear to be quite as simple as I thought, due to the way Haxe interprets types (apparently).

Has anyone had success with something similar to this that could give me a recommendation on how to accomplish it?

2

There are 2 best solutions below

0
On BEST ANSWER

If you want to only get the position of the error you can use haxe.PosInfos as the last argument of your doTest() function and pass that arguemnt to assertEquals() like this:

import haxe.unit.TestCase;

class Main {
    static function main() {
        var r = new haxe.unit.TestRunner();
        r.add(new Test());
        r.run();
    }
}

class Test extends TestCase {
    public function new() {
        super();
    }

    public function testExample() {
        doTest(1, 1);
        doTest(1, 2);
        doTest(3, 3);
    }

    function doTest(a:Int, b:Int, ?pos:haxe.PosInfos) {
        assertEquals(a, b, pos);
    }
}

Online example here

It will give you the position that called doTest() in the error:

Test::testExample() ERR: Main.hx:18(Test.testExample) - expected '1' but was '2'

Another option if you want to add a custom message is to catch the assertEquals() error and rethrow the currentTest with a custom error like this:

import haxe.unit.TestCase;

class Main {
    static function main() {
        var r = new haxe.unit.TestRunner();
        r.add(new Test());
        r.run();
    }
}

class Test extends TestCase {
    public function new() {
        super();
    }

    public function testExample() {
        doTest(1, 1, "Error on test 1");
        doTest(1, 2, "Error on test 2");
        doTest(3, 3, "Error on test 3");
    }

    function doTest(a:Int, b:Int, errorMsg:String, ?pos:haxe.PosInfos) {
        try {
            assertEquals(a, b, pos);   
        } catch(e:Dynamic) {
            currentTest.error = errorMsg;
            throw currentTest;
        }

    }
}

Online example here

Which will give you the following error:

Test::testExample() ERR: Main.hx:18(Test.testExample) - Error on test 2

0
On

You are effectively blending multiple tests into a single one. And Haxe cannot tell where your array element is defined (line number, etc)

What I suggest is to change the signature of doTest to accept Array<Int> instead of Array<Array<Int>> and call doTest multiple times instead of just once. Together with the suggestion from Justo, passing the pos object to assetEquals, you will get the position correctly.