Clean tests are as important as clean code. Same kind of principles apply here.

  1. Test only what is neccessary
  2. Keep code clean

while TDD, is shown to keep test cases to a minimum, this post explains some other ways tests can be organize

Group Tests Together

You should group your tests together. This would make it easier to find your tests

Junit and Jest both allow for grouping of tests.

  • In JUnit 5 you can use @NestClasses
  • In Jest you can use describe

Example:

JUnit:

class MainTestClass

    @Nested
    @DisplayName("Group of tests")
    class MethodNameTests(){

        @Test
        @DisplayName("Test Name")
        class tests{
            ...
        }
    }

Jest:


describe("Group of tests", ()=>{

    it("test name", ()=>{


    })
})

Have global mocks/stub object

Your tests should be as small as possible. Rather than create objects in every test method, Create a dummy stub and use it in all subsiqueny tests

In Junit you can have @BeforeEach and @BeforeAll annotations to have methods run before each test case or test class.

Mock object

Naming

In case I am testing a positive response, I usually name variable as such.

If it is a variable which is bad, prefix it with bad

example:

  • idealHttpHeader
  • goodFuture

If it’s a bad response,

Example:

  • badHttpHeader
  • badHttpHeaderWithoutContentType
  • badFuture

Never generate random inputs. Always use fixed values. 1

Start with method_should_<>_when/with_<>() or itShould_<>_When_<>

This makes you focus on exactly what you are testing.

Though you can remove the should part too.

Example:

  • GroupName: Add function
  • TestName: Should work with negative values: add_shouldWork_withNegativeValues
  • TestName: Should work with positive values: add_shouldWork_withPositiveValues
  • TestName: Should work with floating point values: add_shouldWork_withFloatingPoint
  • TestName: Should raise exception when input is null: add_shouldRaiseException_whenInputisNull

Given When Then

Given When then is how most tests are written.

Start the tests which fixing the input values and mocking -> Given Call the function in test -> when Assert Responses -> then

Size of tests should be less than size of your display

This is a useful guideline which applies to a normal clean code too.

Assertions

Best Practice: One logical assertion per test method. 2

Have clear error messages 1

Aim for asserting behavior and not implementation detail. More coupled your tests are with implementation, harder the refactoring would be.3

Writing tests that run fast

Time complexity of tests shoud be O(1) 4

Cyclomatic time complexity of your tests should be O(1).

  • No loops
  • No if statements

For Spring Boot

Initialize only beans you need using @ContextConfiguration 5

Using @ContextConfiguration won’t start the whole spring infrastructure. This making your tests faster.