Friday, April 8, 2011

What attribute should a good Unit-Test have?

A Unit-Test should

  • produce deterministic result
  • be independent
  • be valid
  • ...

What other characteristics should a test also have?

From stackoverflow
    • not access external resources
    • be readable
  • The Pragmatic Programmers' answer : good tests shall be A-TRIP

    • Automatic
    • Thorough
    • Repeatable
    • Independent
    • Professional
    • Automatable: no manual intervention should be required to run the tests (CI).
    • Complete: they must cover as much code they can (Code Coverage).
    • Reusable: no need to create tests that will only be executed once.
    • Independent: Independent execution of a test should not affect the performance of another.
    • Professional: tests should be considered with the same value as the code, the same professionalism, documentation, etc.
  • Ah. My favorite subject :-) Where to start...

    According to xUnit test patterns by Gerard Meszaros (THE book to read about unit testing)

    • Tests should reduce risk, not introduce it.
    • Tests should be easy to run.
    • Tests should be easy to maintain as the system evolves around them

    Some things to make this easier:

    • Tests should only fail because of one reason. (Tests should only test one thing, avoid multiple asserts for example.)
    • There should only be one test that fails for that reason. (this keeps your testbase maintainable)
    • Minimize test dependencies (no dependencies on databases, files, ui etc.)

    Other things to look at:

    Naming
    Have a descriptive name. Tests-names should read like specifications. If your names get too long you're probably testing too much.

    Structure
    Use AAA structure. This is the new fad for mocking frameworks, But I think it's a good way to structure all your tests like this.

    Arrange your context
    Act, do the things that need to be tested
    Assert, assert what you want to check

    I usually divide my tests in three blocks of code. Knowing this pattern makes tests more readable.

    Mocks vs. Stubs
    When using a mocking framework always try to use stubs and state based testing before resorting to mocking.

    Stubs are objects that stand in for dependencies of the object you're trying to test. You can program behaviour into them and they can get called in your tests. Mocks expand on that by letting you assert if they were called and how. Mocking is very powerfull but it lets you test implementation instead of pre and post-conditions of your code. This tends to make tests more brittle.

    mezoid : +1 the xUnit test patterns book is a must have IMO for anyone wanting to write good unit tests.
    Spoike : +1 but I have to say that book seems to be more about automatic testing rather than "unit testing" per se.
  • An other factors to keep in mind is the running time. If a test runs too long it is likely to be skipped.

    1. Must be fully automatic.
    2. Must not assume any preconditions (product X be installed, file and Y location etc).
    3. Must be person independent as far as running the scripts are concerned. Result can, however, be analysed by subject experts only.
    4. Must run on every beta build.
    5. Must produce a verifiable report.
  • A unit test should be fast: hundreds of test should be able to run in a few seconds.

  • One that I haven't seen anyone else mention is small. A unit test should test for one particular thing and that's all. I try to aim to have only one assert and minimize the amount of setup code by refactoring them out into their own methods. I'll also create my own custom asserts. A nice small unit test IMO is about 10 lines or less. When a test is small it is easy to get a quick understanding of what the test is trying to do. Large tests end up being unmaintainable in the long run.

    Of course, small isn't the only thing I aim for...its just one of the things I value in a unit test. :-)

    Spoike : I believe keeping tests small is a positive side effect from following good unit testing practices.
  • A test is not a unit test if:

    • It talks to the database
    • It communicates across the network
    • It touches the file system
    • It can't run at the same time as any of your other unit tests
    • You have to do special things to your environment (such as editing config files) to run it.

    Tests that do these things aren't bad. Often they are worth writing, and they can be written in a unit test harness. However, it is important to be able to separate them from true unit tests so that we can keep a set of tests that we can run fast whenever we make our changes.

    source: A Set of Unit Testing Rules

0 comments:

Post a Comment