missingfaktor
missingfaktor

Reputation: 92026

Placement of success and failure test cases of the same method

Suppose I have a method named foo which, for certain set of input values, is expected to complete successfully and return a result, and for some other set of values, is expected to throw a certain exception. This method requires some things to have set up before it can be tested.

Given these conditions, is it better to club success and failure tests in one test, or should I maintain these cases in separate test methods?

In other words, which of the following two approaches is preferable?

Approach 1:

@Test
public void testFoo() {
  setUpThings();
  // testing success case
  assertEquals(foo(s), y);
  // testing failure case
  try {
    foo(f);
    fail("Expected an exception.")
  } catch (FooException ex) {
  }
}

Approach 2:

@Test
public void testFooSuccess() {
  setUpThings();
  assertEquals(foo(s), y);
}

@Test
public void testFooFailure() {
  setUpThings();
  try {
    foo(f);
    fail("Expected an exception.")
  } catch (FooException ex) {
  }
}

Upvotes: 2

Views: 3331

Answers (5)

Jordão
Jordão

Reputation: 56467

Approach 3 (extension of 2)

@Before
public void setUpThings() {
  ...
}

@Test
public void testFooSuccess() {
  assertEquals(foo(s), y);
}

@Test(expected=FooException.class)
public void testFooFailure() {
  foo(f);
}

I's good to have focused tests that exercise just one condition at a time, so that a failed test can only mean one thing (Approach 2). And if they all use the same setup, you can move that to a common setup method (@Before). If not, maybe it's better to think about separating related cases into different classes, so that you have not only more focused cases (methods) but also more focused fixtures (classes).

Upvotes: 3

Frank
Frank

Reputation: 15641

Best you go for approach #2.

Why:

Well when an asserts fails the rest of the method is not evaluated... so by putting the tests in 2 separate methods you are sure to at least execute both tests.. failure or not.

Not only should a unit test focus on one specific unit, it should focus on one specific behaviour of that unit. Testing multiple behaviours at once only muddies the water. Take the time to separate each behaviour into its own unit test.

Upvotes: 5

Yogendra Singh
Yogendra Singh

Reputation: 34367

Separate test cases as better for two reasons:

  1. You test case should be atomic
  2. If first assert condition fails, it will not evaluate the second one.

Upvotes: 1

someone
someone

Reputation: 6572

For me Approach 2 is preferable. Because you first test happy path and then fail condition . if some one need to test happy scenarios only you will have it.

Upvotes: 1

duffymo
duffymo

Reputation: 308743

I like approach #2. Separate tests are better.

I don't like how you did test 2. Here's what I'd do:

@Test(expected = FooException.class)
public void testFooFailure() {
  setUpThings();
  foo(f);
}

Upvotes: 2

Related Questions