Download pdf - Unit Testing Guidelines

Transcript
Page 1: Unit Testing Guidelines

@jhooks | 2010 | joelhooks.com

Unit Testing GuidelinesWhy, What and How...

Page 2: Unit Testing Guidelines

@jhooks | 2010 | joelhooks.com

Why?It’s such a pain.there is never enough time!

Page 3: Unit Testing Guidelines

@jhooks | 2010 | joelhooks.com

Sanity.Developers want a productive environment where things work as expected.Unit test can help create this environment at the code level.

Page 4: Unit Testing Guidelines

@jhooks | 2010 | joelhooks.com

Protect your work.We work hard on the functionality that we add to the application.Unit tests serve as a guard against accidental “harm” of code.

Page 5: Unit Testing Guidelines

@jhooks | 2010 | joelhooks.com

Developer documentation.Well written unit test provide excellent documentation for other developers.Unit tests describe how a piece of logical code should work in a way that English language docs often can’t.

Page 6: Unit Testing Guidelines

@jhooks | 2010 | joelhooks.com

Collective ownership.Code that is protected can be worked on by anybody with greater assurance that nothing will be accidentally broken.

Page 7: Unit Testing Guidelines

@jhooks | 2010 | joelhooks.com

Code can be constantly improved upon with less fear of accidental breakage.Unit tests verify that changes don’t break the existing logic.

Fearless refactoring.

Page 8: Unit Testing Guidelines

@jhooks | 2010 | joelhooks.com

What should be tested?

ModelsService classes

Commands

Utility classes

any other logical code

Page 9: Unit Testing Guidelines

@jhooks | 2010 | joelhooks.com

When to write tests...

Before you write the code?

After you write the code?

Page 10: Unit Testing Guidelines

@jhooks | 2010 | joelhooks.com

Test Driven Development

10 Ways to Improve Your Code - Neal Ford

Page 11: Unit Testing Guidelines

@jhooks | 2010 | joelhooks.com

Writing unit tests firsts lets you focus on the functionality you are adding.Write the test. Write the code. Tests pass. Done.

Less fear.

Page 12: Unit Testing Guidelines

@jhooks | 2010 | joelhooks.com

Tests written before production code ensures that the production code is tested.Tests are not an afterthought.

Ensure test coverage.

Page 13: Unit Testing Guidelines

@jhooks | 2010 | joelhooks.com

Wait... What?!Writing tests before the production code eliminates the need for a massive testing effort after the code is written.

Reduces tedium of testing.

Page 14: Unit Testing Guidelines

@jhooks | 2010 | joelhooks.com

Testing first ensures that the production code can be tested.Testing after often results in the discovery that the code isn’t testable without refactoring. Refactoring that isn’t protected by tests.

Guarantees testable code.

Page 15: Unit Testing Guidelines

@jhooks | 2010 | joelhooks.com

Like most practices, TDD is no guarantee of quality or success in development.It is a tool.

TDD is not a guarantee.

Page 16: Unit Testing Guidelines

@jhooks | 2010 | joelhooks.com

Test driven development is not required.Try it out. It can be painful to start, but once you get a rhythm going the benefits are very real.

So when should I test?

Page 17: Unit Testing Guidelines

@jhooks | 2010 | joelhooks.com

automated

repeatable

run by anybody

future use

fast

single push

easy

What is a good unit test?

Page 18: Unit Testing Guidelines

@jhooks | 2010 | joelhooks.com

Unit tests are by developers for developers. Quality over quantity please.

Page 19: Unit Testing Guidelines

@jhooks | 2010 | joelhooks.com

Developers will run and use tests they trust.A trustworthy test is free of bugs and does what it says it does.

Trustworthy

Page 20: Unit Testing Guidelines

@jhooks | 2010 | joelhooks.com

Most tests are not meant to be temporary. They change for very specific reasons

Bugs in production code

Bugs in the test

API updates in the production code

Test is no longer valid or is not needed

To eliminate duplication

Tests are written to last.

Page 21: Unit Testing Guidelines

@jhooks | 2010 | joelhooks.com

Logic in a unit tests makes the test harder to read and understand. There is more likely to be bugs in the test. It can also make the test harder to name.

There should be no switch, if, or else statements.

There should be no for each, for, or while statements.

The test is a series of method calls with no control flow.

There is no logic in the test.

Page 22: Unit Testing Guidelines

@jhooks | 2010 | joelhooks.com

A unit test is testing a single behavior. Testing multiple things makes a test hard to understand.

Assert only one thing.

Should be easy to name (you don’t need an and in the name).

When it fails, it is clear what actually failed.

Only one thing is tested.

Page 23: Unit Testing Guidelines

@jhooks | 2010 | joelhooks.com

Unmaintainable tests are ignored and are often simply removed from the suite.Unmaintainable tests cannot be trusted.

Maintainable

Page 24: Unit Testing Guidelines

@jhooks | 2010 | joelhooks.com

Unit tests are written against the public contract of the unit being tested. We shouldn’t be trying to test private methods.

Private and protected methods can affect the outcome of public methods.

Does it make sense to make a private method public?

Test the results of the public API that uses private methods

Is the private method pure utility? Would it makes sense as a static method of a utility class?

Test the API

Page 25: Unit Testing Guidelines

@jhooks | 2010 | joelhooks.com

Avoiding the duplication of code in unit tests is as, if not more, important than it is with production code.

Create helper methods like factories to assist in setup of common items

Use setup methods for setup of items common to all test methods in the case

Setup should be as short, simple, and as easy to read as possible

Avoid duplication (DRY)

Page 26: Unit Testing Guidelines

@jhooks | 2010 | joelhooks.com

Don’t try to use Parsley, configure and access remote services, or otherwise try to simulate the broader application in a unit test.

Are test methods constrained to a linear order of execution?

Is the test calling other test methods?

Do tests share global state?

Test behaviors, not workflows.

If shared state can’t be avoid, be sure to reset it in the teardown.

Tests should be isolated.

Page 27: Unit Testing Guidelines

@jhooks | 2010 | joelhooks.com

Unit tests are testing specific single behaviors. It seems like more work because results might be related, but the results should be verified independently.

Give each assertion its own test

Give each test a meaningful name

This makes failures easy to understand and fix

Avoid multiple asserts.

Page 28: Unit Testing Guidelines

@jhooks | 2010 | joelhooks.com

Tests shouldn’t make assumptions about the implementation of behavior, instead they should focus on the results of the behavior.

Does the test specify purely internal behavior of the unit?

Is the test using complicated mock objects when simple stubs would be enough?

Does the test assume specific results when it isn’t required?

Avoid over-specification.

Page 29: Unit Testing Guidelines

@jhooks | 2010 | joelhooks.com

Code in tests is easy to understand quickly. What is being tested is recognizable instantly without deciphering or translation.Readable tests are more trustworthy and maintainable.

Readable

Page 30: Unit Testing Guidelines

@jhooks | 2010 | joelhooks.com

If all tests are named in the same pattern they will be easy to read..

Standard test names.

methodUnderTest_descriptionOfState_expectedBehavior()

Page 31: Unit Testing Guidelines

@jhooks | 2010 | joelhooks.com

As with all code, good variable names can help greatly in making the code readable.

Avoid abbreviations

Use static constants instead of hardcoded values

Good variable names.

Page 32: Unit Testing Guidelines

@jhooks | 2010 | joelhooks.com

Setup -> Action -> Assert

Consistent test structure.

[Test]public function doSomeWork_workWasDone_isTrue(){ //setup var aDependency:ISomeDependency = new SomeDependency(); //execute behavior aDependency.doSomeWork(); //verify expected state is valid assertThat(allTestsNeedThis.workWasDone, isTrue());}


Recommended