Is it OK to have multiple asserts in a single unit test?

  • In the comment to this great post, Roy Osherove mentioned the OAPT project that is designed to run each assert in a single test.

    The following is written on the project's home page:

    Proper unit tests should fail for exactly one reason, that’s why you should be using one assert per unit test.

    And, also, Roy wrote in comments:

    My guideline is usually that you test one logical CONCEPT per test. you can have multiple asserts on the same object. they will usually be the same concept being tested.

    I think that, there are some cases where multiple assertions are needed (e.g. Guard Assertion), but in general I try to avoid this. What is your opinion? Please provide a real world example where multiple asserts are really needed.

    How do you do mocking without having multiple assertions? Each expectation on the mock is an assertion in itself, including any order of calls you impose.

    I've seen the one-assert-per-method philosophy abused in the past. An old co-worker used a funky inheritance mechanism to make this possible. It led to a lot of sub-classes (one per branch) and lots of tests that did the same set-up/tear-down process only to check the different results. It was slow, hard to read and a severe maintenance problem. I never convinced him to switch back to a more classic approach. Gerard Meszaros book talks about this topic in detail.

    I think as a general rule of thumb you should try to minimize the number of asserts per test. However, as long as the test sufficiently narrows the problem to a specific place in the code, then it's a useful test.

    I've seen cases where multiple asserts were used instead of `RowTest` (MbUnit) / `TestCase` (NUnit) to test a variety of edge-case behaviors. Use the proper tools for the job! (Unfortunately, MSTest doesn't seem to have a row-test capability yet.)

    @GalacticCowboy You can get similar functionality of `RowTest` and `TestCase` using test data sources. I'm using a simple CSV file with great success.

    FWIW, XCT tests in XCode allow multiple asserts within a single test, however they can run each assert regardless of previous failures, so a test with five asserts will get results for the other four even if the first fails

  • I don't think it's necessarily a bad thing, but I do think we should strive towards only having single asserts in our tests. This means you write a lot more tests and our tests would end up testing only one thing at a time.

    Having said that, I would say maybe half of my tests actually only have one assert. I think it only becomes a code (test?) smell when you have about five or more asserts in your test.

    How do you solve multiple asserts?

    Like this answer - i.e. its OK, but its not, in the general instance, *good* (-:

    I do it a bit. For example, if I'm testing comparability, and that `ItemA > ItemB` I'll also assert that `ItemB < ItemA` in the same test.

    Passing an argument into a single argument method can result in several properties being changed of that object. Hence a simple operation can require multiple asserts. Take `Stream.Write`

    @jgauffin wouldn't those be seperate tests though? eg. SomeMethod_Alters_FooProperty(), SomeMethod_Alters_BarProperty() etc. The unit tests would be identical apart from the assertion.

    Ehh? Why would you do that? the method execution is exactly the same?

    A single assert per unit test is a great way to test the reader's ability to scroll up and down.

    bad thing strive towards only having single asserts code (test?) smell

    @Tom, I have as a requirement of my test runners that they link to the code - e.g. If i double click on a failed test it should take me straight to the code file. Console runners obviously are more difficult!

    @jgauffin It depends whether you are using unit test to mechanically execute the code or to define the expected behavior. If you take the behavior approach (which I prefer) you end up with 2 tests.

    a case where you need multiple assertions for me is when i need to test math/geometry functions. i add assertions for the basic cases, corner cases, and then a couple random ones. so if i need to test some point conversion between views, for example, i will add the points to the corners of the view, a point inside the view, and a point outside the view.

    Any reasoning behind this? As is, this current answer just states what it should be, but not why.

    Strongly disagree. The answer doesn't list any advantage of having single assert, and the obvious disadvantage is that you need to copy-paste tests only because an answer on the internet says so. If you need to test multiple fields of a result or multiple results of a single operation, you absolutely should assert all of them in independent asserts, because it gives far more useful information than testing them in a big blob-assert. In a good test, you test a single operation, not a single result of an operation.

    woah, it's a code smell to have 5 or more asserts? definitely not and depends on the situation.

    Link returns a 404

    @JacoPretorius ah my HTTPS Everywhere extension was forcing the link to HTTPS, which is a 404. HTTP works just fine.

License under CC-BY-SA with attribution

Content dated before 6/26/2020 9:53 AM