Test driven development TDD best practices and notes

I was asked to discuss test driven development with our teams and did a bunch of research to share with everyone. Below is what I presented.

Focusing on unit tests, other layers of TDD is:
– regression tests (when things are changed old bugs don’t come back)
– integrations tests (multiple steps, a flow of logic)
– e2e tests (a user journey flow from start to finish)

Research the layers of tdd you could find useful tests to help add to a project’s stability.

The argument for routine

Make TDD a part of your coding routine. The initial setup of the tests might take some TLC and time, but once that is done you should rarely have to do much new development. Once TDD becomes habit it becomes easier to to do.

The below is a combination of online research, experience and advice given by Robert C. Martin in Clean Code.

The 3 laws of TDD:

1. You have to write a failing unit test before you write any code.
2. You must not write more than was is sufficient to make the test fail.
3. You must not write more production code than what is sufficient to make the test pass.

Structure of a test:

Build, Operate, Check or “Arrange, Act, Assert,” (sometimes there’s a 4th step – teardown – cleans after test ends – most frameworks should handle that for you)

1. Build / Arrange

What data do you need? What stubs should you call in? On backend you might want to create a fake model to use.

2. Operate / Act

Usually: Call a method. Or pass values into a method.

3. Check / Assert

Check the result of the Operate / Act step. Is it what you expected?

Make sure the tests are clean

Make sure you give as much thought to the quality of your tests as you do for the quality of your production code. If you let your tests rot, your code will rot.

Clean tests = readability; clarity, simplicity, density.

Guidelines:

One assert per test. Same way that in your code you look at DRY and single responsibility – if you have to assert multiple things in a test relook your code, you are probably doing too much in the actual code of method you are testing.

Test a single assertion.

FIRST

Clean tests follow with 5 FIRST rules, as mentioned in Clean Code:

Fast

– runs quickly, you don’t want to wait 10 minutes for the tests to run, no one will run the tests. The ideal situation is that the tests run continuously while you are coding.

Independent

– one test should not rely on another test running

Repeatable

– You should be able to run tests in staging, prepared, prod. You should not hard code tests to a specific environment.

Self-Validating

– No manual interpretation needed (human eyes don’t define if its passing or not)

Timely

– Should be written before your code.

Avoid

Be aware of these and avoid them

Tightly coupled tests = harder to refactor code.
Tests that depend on other tests to run.
Too many assertions in one test.
Testing other parts of the code that are outside of the method you are testing.

Remember: Test rot = code rot. Keep tests clean.

TDD should be easy and quick. The first warning sign that you are doing incorrect tests and not following best practice is if they take a lot of time.

Goal of TDD

Write tests that “have your back”.
Tests should be quick and easy.
Forces you to write neater code. Code quality goes up. Bugs go down. Rewrites become less, refactoring over rewrites.