Writing Tests Effectively

48
Writing Tests Effectively Codeweavers Development Series

Transcript of Writing Tests Effectively

Writing Tests EffectivelyCodeweavers Development Series

IntroductionWhat do we actually mean by Unit Test?Why we write testsApproaches to writing testsWhat we can do going forward

2

Unit Test DefinitionIn computer programming, unit testing is a software testing method by which individual units of source code, sets of one or more computer program modules together with associated control data, usage procedures, and operating procedures, are tested to determine whether they are fit for use. Intuitively, one can view a unit as the smallest testable part of an application. In procedural programming, a unit could be an entire module, but it is more commonly an individual function or procedure. In object-oriented programming, a unit is often an entire interface, such as a class, but could be an individual method.

Unit Testing - Wikipedia

3

How big is a Unit TestIt depends…

4

How big is a Unit Test● OO Languages

○ Test at method level○ Test Fixture per class

■ 1 to Many for every method

5

How big is a Unit Test● Functional

○ One test module for every domain○ One to many tests for each function

6

Why Test?Or rather, why don’t people write tests?

● No Time to write tests○ Probably because you’re spending so long debugging

● Tests that add value haven’t been written○ How can we do this?

7

Why Test?● Be playful!

○ Experiment!

● Can play around in your test framework● Gain huge confidence in your codebase

8

Who are we testing for?2 Approaches● Write Unit Tests for yourself

○ How would you want to maintain it?

● Put the team first○ They can extend your code with confidence○ Provide your team with guidelines to work to

9

...Still not convinced?

10

Unit Tests are a waste of time!

Unit Tests are a waste of time● Are writing tests making you more productive?

○ If not then stop writing them!

● Kill wasteful tests○ You want plenty of unit tests that are really helpful!○ Keep test suites quick to keep them useful

■ 10 second test suites?!?11

Unit Tests are a waste of timeMaybe invest in writing better Unit Tests?

12

Unit Tests are easy!● Easy to write

○ Easy to write poorly

● What do we do wrong?○ Strongly couple our tests to our code○ Thinking about yourself○ Not getting ‘Bang for the bucks’

13

TDD vs Unit Tests

Not the same thing!

14

TDD vs Unit TestsA test you wrote to do TDD may not be valuable for you in the long term

Just because a test was useful to help you create a feature doesn’t mean it needs to

stay

15

TDD vs Unit Tests● Maybe the test doesn’t add value

○ What is the ROI on having this test?○ How many phone calls does it prevent?

● Maybe deleting it isn’t right but…○ How about making it more useful?

16

TDD vs Unit Tests● If this test was failing right now what clues

would you want it to give you to help you solve the issue faster○ Work together to find out what that is and then

change your test accordingly○ Test goes from helping you deliver to helping you

maintain value17

TDD● TDD is a technique to help you write code

and defining a nice way to use it○ Not necessarily a good way to ensure that feature is

well tested if it even needs lots of tests at all○ How much time will be spent maintaining the tests?

18

Approachability● Let’s imagine a 6 month old failing test

○ What clues does it give me?○ Does it explain the domain?○ How much test code do you have to wade through to

find out what it does?○ Is it DRY?

■ This doesn’t mean the least characters possible…

19

Let’s talk about DRY● Often see a broken test that is unrelated

○ Wouldn’t it be great if you could quickly see what was going on...

○ Then you wouldn’t be so annoyed!

Repeating yourself to help others understand what is going on is probably a

good idea 20

Let’s talk about DRY

Apply DRY on a test suite levelApply DRY on a single test

21

Let’s talk about DRY● In a group of tests you can repeat things

○ What happens when 2 out of 5 tests in a test fixture fail?

○ Duplication can lead to more maintainable tests○ Always ask what is the value of the test?

22

Data Builders● Avoid using ObjectMother pattern

○ Breaks down when needing different data○ Personas -> Bob & Jane both have different attributes

● Create data builders - Nat Pryce○ http://www.natpryce.com/articles/000714.html

23

Some things to avoid● Avoid

○ Looping○ Language Constructs○ Reflection

Stay in domain code as much as possible

24

MaintainabilityTests should be just as maintainable as the rest of the codebase

We don’t need to approach writing tests in quite the same way as production code

25

Different ThinkingApproach tests in a way where readability is more important than performance

Milliseconds don’t matter (probably)

However, test suites need to be fast!

26

Too many tests● Too many tests… not enough tests…

○ Both are suboptimal

● Not enough then too long spent debugging● Too many then too long to run and maintain

○ Both lead to WASTE

27

Code Coverage● Useful!

● Not looking for 100% code coverage○ End up doing random things like testing getters and

setters○ Don’t have to test third party libraries

28

What to test?The most complex parts of the system that add the most value

Lots of tests in Allium for exampleMaybe too many?

29

Test different things● What different types of tests?

○ Fast tests - mock things out○ Database tests - slow but useful?○ Etc.

Want test suite to be fast but depends on needs ● Maybe you need one database test per suite?

30

Test Categories● State Verification

○ Check the state of the system after it has been exercised and compare it to the expected state■ e.g. Assert.AreEqual(a, b)

● Set up -> Call a function -> Check result

31

Test Categories● Behaviour Verification

○ Capture the indirect outputs of the test as they occur and compare them to the expected behaviour

● Mock out -> Verify behaviour happens

32

Test Categories● Both are fine!

○ Consider and think which style suits you or the situation best

● Probably a combination of both

33

Unit Tests● Solitary Unit Test

○ Tests that don’t cross boundaries○ Test a single class at a time

● e.g. Library -> Book○ Library tests still pass if book changes

34

Unit Tests● Sociable Unit Test

○ Tests that cross boundaries○ Test multiple classes at a time

● e.g. Library -> Book○ Library tests fail if book changes.

35

Unit Tests● Cascading failures can occur with sociable

tests○ Solitary tests prevent this happening

36

COMBO TIME● Write lots of solitary unit tests

○ As many as you can

● One or two sociable unit tests○ Makes sure that things work together but don't need

to test edge cases with slow sociable tests

37

Stub vs Mock● Mock used in Behaviour based tests

○ For Verification

● Stub you don’t verify○ Return canned responses

38

Going away● Write lots of fast solitary tests

○ With a few sociable ones too

● Keep your tests approachable● Keep your tests maintainable

○ Don’t freak out by breaking some of the production code rules to achieve these

39

Going away● Make expected literals

○ Don’t call method for expected values○ Convert objects to literals or write custom assertions

(that are also tested) - Think Money object

● Get rid of loops○ Split into individual tests

40

Going away● Don’t use reflection

○ Being clever in tests isn’t a good idea○ Avoiding LINQ might be a good idea too

● Use Data Builders○ Don’t use Object Mother pattern

41

More controversial● 1 assertion per unit test rule

● Get rid of setup methods○ Failing tests don’t alert you to go look in the setup○ Write whole story in the tests

42

Higher Level TestsAlso useful

Such as Integration tests

Unit Tests are just the beginning...

43

Higher Level Tests

44

How long should you spend?● 50/50?

● Write Tests -> Write Simplest Thing -> Refactor Test○ Spending longer on tests then?○ Don’t test everything though so probably not more

time45

How long should you spend?● Anything between 30 and 50% time - unless

your TDDing and then deleting so maybe longer as TDD is part of design phase

● Basically, however long you need to!

46

Wrap up● Don’t give up on tests

● Look for ways to improve ROI in writing tests○ Keep reading - Blogs, Books, Podcasts

47

ReadingWorking Effectively with Unit Testshttps://www.goodreads.com/book/show/22605938-working-effectively-with-unit-tests

Growing Object-Oriented Softwarehttps://www.goodreads.com/book/show/4268826-growing-object-oriented-software-guided-by-tests

Nat Pryce - Data Buildershttp://www.natpryce.com/articles/000714.html

48