Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Should you do an assert statement inside a loop?

Tags:

testing

When we have multiple values for which we would like to test a given method should we loop through the values in a single test?

Or is it incorrect as in case of failure it might be harder to identify the cause?

Something like this:

testSomething(){
    List myValues = {'value1', 'value2', 'value3', ...}

    for(value: myValues){
        assertTrue(Something(Value))
    }
}
like image 396
João Almeida Avatar asked Jan 24 '17 15:01

João Almeida


People also ask

When should I use assert?

Documenting Your Code With AssertionsThe assert statement is an effective way to document code. For example, if you want to state that a specific condition should always be true in your code, then assert condition can be better and more effective than a comment or a docstring, as you'll learn in a moment.

Is it good practice to use assert in Java?

An assert is inappropriate because the method guarantees that it will always enforce the argument checks. It must check its arguments whether or not assertions are enabled. Further, the assert construct does not throw an exception of the specified type. It can throw only an AssertionError .

Should you use loops in unit tests?

Yes you can have loops in unit test, but with caution. As mentioned by Alex York, loops are acceptable if you test one thing; i.e. one expectation. If you use loops, then I recommend that you must do two things: As mentioned above, test for a non-empty iteration set.

Does assert stop execution?

A triggered assertion indicates that the object is definitely bad and execution will stop.


1 Answers

Not if you can avoid it

By which I mean, depending on what you're using to do your unit tests, you might not be able to realistically avoid it. In that case, do as needs must

If you run your assert in a loop, you effectively have one test which is testing an arbitrary number of things. That's going to get confusing.

What you want is multiple tests which test one thing each.

Some test frameworks (like NUnit for C#) allow you to define a test that takes parameters and then define the values to repeat the test with.

e.g.

[TestCase(1, 1, 2)]
[TestCase(2, 3, 5)]
[TestCase(0, -1, -1)]
public void MyTest(int a, int b, int expected) {        
    Assert.AreEqual(expected, a + b);
}

If your framework supports that, it's wonderfully easy to do.

Alternatively, if you're using a script language (e.g. javascript), you might be able to define your tests in a loop, rather than the asserts.

e.g.

describe('My tests', function() {
    var testCases = [
        {a: 1, b: 1, expected: 2},
        {a: 2, b: 3, expected: 5},
        {a: 0, b: -1, expected: -1}
    ]

    testCases.forEach(function(t) {
        it(`Adds ${t.a} and ${t.b} correctly`, function() {
            assert.equal(t.expected, t.a + t.b);
        });
    });
})

This defines many tests, testing a single thing. Not one test testing many things. Which subsequently makes it much easier to see which one fails when it does.

like image 127
JamesT Avatar answered Sep 30 '22 20:09

JamesT