3

I try to realize unit tests by respecting best practices. One of the rules is to use only one "assert" by method. I would like realize several tests by method because there is a heavy treatment which is made at the beginning of every method (insertion in database - > 5 seconds).

I developed this solution, is it a good practice?

String failuresMsg = "";
if(9 != var1) 
    failuresMsg += "[var1 <9," + var1+">]";
if(9 != var2) 
    failuresMsg += "[var2 <9," + var2+">]";
if(9 != var3) 
    failuresMsg += "[var3 <9," + var3+">]";
if(9 != var4) 
    failuresMsg += "[var4 <9," + var4+">]";

assertEquals("", failuresMsg);

2 Answers 2

3

One of the rules is to use only one "assert" by method.

No you should limit yourself to test a scenario by method of test. It is not the same thing.

String failuresMsg = "";
if(9 != var1) 
    failuresMsg += "[var1 <9," + var1+">]";
if(9 != var2) 
    failuresMsg += "[var2 <9," + var2+">]";
if(9 != var3) 
    failuresMsg += "[var3 <9," + var3+">]";
if(9 != var4) 
    failuresMsg += "[var4 <9," + var4+">]";

assertEquals("", failuresMsg);

Generally, when you have values acceptable according to a range, you should at least test the limits of this range and one or several inner values of the range.

If if take your test, it would give 2 methods of tests (or more according to the way of seeing things) because I have two distinct scenarios :

  • the value is acceptable

  • the value is not acceptable

For each scenario, I may perform any assertions that I need if the code and the maintainability of tests stay good.

Here is a sample code :

@Test
public void doMethodWithAcceptableValues(){
   int testValue = 0;
   Assert.assertTrue(objUnderTest.doMethod(testValue));
   testValue = 100; // limit value
   Assert.assertTrue(objUnderTest.doMethod(testValue));
   testValue = 50; // middle value 50. it is an example
   Assert.assertTrue(objUnderTest.doMethod(testValue));
}

@Test
public void doMethodWithNotAcceptableValues(){
   int testValue = -1;
   Assert.assertFalse("-1 not acceptable", objUnderTest.doMethod(testValue));
   testValue = 101; // limit value
   Assert.assertFalse("101 not acceptable", objUnderTest.doMethod(testValue));
}

Nothing prevents you from testing all values of the interval if the interval is not too much important, you could use JUnit mechanisms for it (Parameterized tests) or create your own method which perform this logic with a loop for example.
In many cases, home processing is more simple, readable and maintainable.

Sign up to request clarification or add additional context in comments.

3 Comments

I didn't specify, variables are strongly bound, and this test corresponds to check a single idea. The problem to have several assert in the same test, in the case of several failures, we see only the result of the first failure.
Indeed but it should not be a problem because which matters when a test fails is understand which scenario fails. If the method of test of a scenario failed, it should not matter if other assertions in the method could not fail because the test has existed before since normally you should correct the failure method and re-run the test to check if the problem is corrected. Splitting each assertion in a method multiplies the tests and the complexity of the testing code. It has a cost because more your have code, less it is readable, more is it complex and more maintaining it is harder.
you are welcome :) It is above all the vision that I have build about tests during my experience
3

I think,You can use JUnitParamsRunner on Your tests. If You use this, You can add parameter to test method. Then, You can remove if's from method body.

Example:

@RunWith(JUnitParamsRunner.class)
public class TestSomething{

  @Test
  @Parameters({ "A", "B", "C" })
  public void shouldDoSomething(String s){

    assertEquals(s, "s");
  }

  //OR

  @Test
  @Parameters(method = "data")
  public void shouldSomething(String a, String b){

   assertEquals(a,b);
  }

  @SuppressWarnings("unused")
  private Object[] data() {
  return $( //
     $("A", "B") //
  );
 }
}

I think, is better and more readable then meny if's in test, because You have only one assertion, start value is not changed in test time, and parameters is really easy to extension and maintainable.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.