8

Is having more than one assert per test a really bad smell? I usually try to follow the “arrange, act, assert” pattern as well as the single assert per test guideline. I think having clean, small, isolated tests is pure awesomeness. For the most part I manage to do this. However, sometimes I find myself asserting “pre-conditions” right after my arrange like so:

'arrange:
'pre-conditions:     
     Assert the arrange worked
'act:
'assert:

Is my test testing too much? Is it caring about things it shouldn’t care about? I’d love to hear some opinions on this.

dalcantara
  • 1,613
  • 2
  • 21
  • 35
  • possible duplicate of [Is it bad practice to have more than Assert in a unit test?](http://stackoverflow.com/questions/762512/is-it-bad-practice-to-have-more-than-assert-in-a-unit-test) – Péter Török Aug 31 '10 at 12:54
  • 1
    I don't think this is a duplicate, if you look at it from the perspective of validating test fixture setup vs. using multiple asserts to validate results. It might be helpful to rename the question to reflect this. – Jay Aug 31 '10 at 13:31
  • I'll rename to reflect the suggestion. @Carl Manaster: Awesome beard dude! – dalcantara Aug 31 '10 at 14:54

3 Answers3

7

As I said here, I think perhaps our best practice should be, not Arrange-Act-Assert, but rather Arrange-Assume-Act-Assert. That before Acting, we assert that the desired result of the Action is not already in effect. This isn't exactly the same as what you are asking; generally I don't think it's important to verify the setup, because setup errors tend to manifest themselves pretty "loudly" in any case; but it's a good reason to have a second assert in the test.

Community
  • 1
  • 1
Carl Manaster
  • 39,912
  • 17
  • 102
  • 155
2

I think having to use Assert to validate the setup is suboptimal, as it muddies the results (it might be hard to figure out what you're testing, if just looking at the output).

I recognize that there are times when this is necessary, or you just want to make sure that everything is being tested in the way you intend.

My practice is to use Debug.Assert (in C#) for this purpose, so that the setup validation does not become part of the test output.

You might be able to achieve the same in other languages by throwing an exception if the setup does not put the system into an expected state.

Different test runners may handle this differently, so you should make sure that this approach has the desired effect (tests fail, but no extra report output as long as the Debug.Assert passes or no exception thrown).

Jay
  • 56,361
  • 10
  • 99
  • 123
  • All these are great answers. However, I'm choosing Jay's because I like how Debug.Assert reads in the test. Thanks again. – dalcantara Sep 23 '10 at 15:34
  • What is less convenient is that Debug.Assert is only for debugging. You might run tests of your release in a CI which would then test different code (e.g. Debug.Assert will no longer be there). You could opt to use Trace.Assert but to me it feels a bit strange to user Debug.Assert and Trace.Assert in tests since it seems they are meant to show message boxes according to the docs: https://docs.microsoft.com/en-us/dotnet/api/system.diagnostics.debug.assert?view=net-6.0 Did anyone find an alternative? It almost seems as if it would be useful to have preconditions tests in the test framework. – Brecht De Rooms Dec 09 '21 at 11:25
1

I would not use a vanilla "Assert" for that but rather Assert.Inconclusive (MSTest)¹. The test has not failed, so you don't want to fail the test run.

1) Assume in JUnit and NUnit I believe.

Michael Lloyd Lee mlk
  • 14,561
  • 3
  • 44
  • 81