Keeping a check on your code's behavior

Unit tests are used to test the semantics of your code; To verify it works as expected and keeps working as expected through changes.

Unit tests are light-weight and fast. Don’t get tangled up in hard-to-handle dependencies such as loading databases or instantiating long sequences of objects before you get to the actual testing, use mocks and stubs to simulate your first order dependencies. Or use Proxies to have non-local collaborators contribute to your test.

A unit test is quick to execute and it should be executable in the context of your development environment.

Testing from start to finish, automagically

In a functional test, you test the features that the system offers as a whole, seen from the end user’s perspective.

In the previous millennium such a test would be planned by a person with domain knowledge, then executed prior to every release by testers performing manual operations based on written instructions.

A more contemporary strategy is to have the person with domain knowledge manage a team of developers, who are actually implementing the tests as code, and then give the software developers access to execute these test in their production-like environments.

Test data as code

Management and maintenance of your test data is considered part of your Quality Assurance strategy. Your test data is versioned and stored as an artifact.

This implies that you separate your test data from the actual tests, which in turn comes with the benefit of easily running test suites with different, versioned data sets.

Test suites becomes self-contained, each with their own easy reproducible setup and tear-down steps, something that will later enable you to run your test suites independently of each other - maybe even selected on output from previous verification steps in your pipeline.

Only run the required tests - you know which ones I'm talking about! Right?

When your test cases are self-contained with individual setups and tear-downs and they trace to related functions and features, you are able to analyze a given change set, place it in context of a limited amount of features and derive its relevant test cases.

Then you can construct an adaptive test suite on the fly and execute that on a production-like environment.

By running a small and relevant subset of functional tests, you can add functional testing to the short feed-back loop.

Murphy and me - Errors will eventually happen in production

A word of precaution; testing in production is not to be confused with releasing untested code.

It starts with acknowledgement that all serious problems are discovered in production and occurred because unforeseen things happened.

Deliberately go to your production environment and do unforeseen things like turn off a server, kill a process, pour coffee on your keyboard, upgrade a service during high-load.

If your system is built to survive it, then it should! You’re only sure it will if you (dare) test it.