71
© 2015 McWest Corporation Spock TDD Tests as Assets not Afterthoughts by Brian Westrich, McWest Corp. bw@ mcwest.com 1

Westrich spock-assets-gum

Embed Size (px)

Citation preview

Page 1: Westrich spock-assets-gum

© 2015 McWest Corporation 1

Spock TDD

Tests as Assets not Afterthoughts

by Brian Westrich, McWest [email protected]

Page 2: Westrich spock-assets-gum

© 2015 McWest Corporation

About me• TDD developer since 1989• Minneapolis-based

• Consultant at McWest Corp. (www.mcwest.com)• Custom software design, development,

and mentoring• Historical focus: Java/Groovy• Increasing focus: JavaScript

• Recently consulted for large enterprise successfully using TDD

Page 3: Westrich spock-assets-gum

© 2015 McWest Corporation

Minneapolis development projects: Light-rail, Vikings stadium

Page 4: Westrich spock-assets-gum

© 2015 McWest Corporation 4

Agenda• History of TDD• Spock TDD case study• Spock tests as assets • Testing effectively• TDD in teams• TDD mantras• Summary / Conclusion• Resources

Page 5: Westrich spock-assets-gum

© 2015 McWest Corporation 5

History of TDD

Page 6: Westrich spock-assets-gum

© 2015 McWest Corporation 6

Timeframe? Automated dev tests are Developers say

Pre - 2000 a curiousity “Why is he testing?”

Early 2000s a threat “Don’t check that in.”

Mid 2000s a given “Good idea!”

Late 2000s an obsession “We need 100% coverage.”

2010 - now an obligation, an afterthought

“I’ve finished everything except the tests.”

Future? an asset? “My project needs tests, and I want to write them.”

Page 7: Westrich spock-assets-gum

© 2015 McWest Corporation 7

Presentation Goal• Help you create tests that are Assets not Afterthoughts.• Make you want to spend more time writing tests.

Page 8: Westrich spock-assets-gum

© 2015 McWest Corporation 8

Survey• 60 attendees (room nearly full)• Development languages

• Java (all), Groovy (all), scala (none), clojure (none), JavaScript(10), other

• Testing tools • Junit (all), TestNG(2), Spock (most), other

• OS (development)• Mac (1/4), Windows (2/3), Linux (handful)

• IDE• IntelliJ (1/2), STS (4), Bare eclipse (1), Sublime (1), emacs, nano,

vi, other• TDD (3)

Page 9: Westrich spock-assets-gum

© 2015 McWest Corporation 9

Spock TDD Case Study

Page 10: Westrich spock-assets-gum

© 2015 McWest Corporation 10

Calculating Calories from Proximates• Calories =

4 * carbs + 9 * fat + 4 * protein + 7 * alcohol

Page 11: Westrich spock-assets-gum

© 2015 McWest Corporation 11

Additional requirement: Missing proximates• Don’t calculate calories if we don’t have proximate values

Page 12: Westrich spock-assets-gum

© 2015 McWest Corporation 12

Problem• Calories aren’t calculating for most of our foods

New Requirement: If alcohol value is missing, assume it is zero

Page 13: Westrich spock-assets-gum

© 2015 McWest Corporation 13

New requirement: Missing ingredient values• If ingredients are missing one or more proximate values, flag the

calorie value as having missing ingredient values

Page 14: Westrich spock-assets-gum

© 2015 McWest Corporation 14

New requirement: Ingredient missing alcohol• If alcohol is missing in one of the ingredients, don’t flag the calorie

value as having missing ingredient values.

Page 15: Westrich spock-assets-gum

© 2015 McWest Corporation 15

Initial algorithm Final algorithm

Case Study Takeaway:Functionality starts simple, becomes complicated

Page 16: Westrich spock-assets-gum

© 2015 McWest Corporation 16

With specs…• Implementation can be

refactored, is maintainable, and is documented

Without specs…• Implementation

becomes unmaintainable (imagine first implementation patched to implement final implementation) and undocumented

Case Study Takeaway

Page 17: Westrich spock-assets-gum

© 2015 McWest Corporation 17

Case Study Takeaway: Reflections• Is the final where table too large? • If so, how would you break it into smaller tables? • Extra credit: if you break the test up, what new test(s) might you

introduce to show how all requirements relate to each other?

Page 18: Westrich spock-assets-gum

© 2015 McWest Corporation 18

Spock TDD Case Studyhttps://github.com/bwestrich/tdd-spock/blob/master/src/test/groovy/mcwest/casestudies/calories/README.md

Page 19: Westrich spock-assets-gum

© 2015 McWest Corporation 19

TDD Benefits and Costs• Benefits

• Immediate developer feedback• Improves design• Documents system• Allows safe refactoring

• Costs• Time to write tests• Time to run tests• Harder to refactor?

Page 20: Westrich spock-assets-gum

© 2015 McWest Corporation 20

Spock Tests as Assets

Page 21: Westrich spock-assets-gum

© 2015 McWest Corporation 21

What I’ll cover on Spock in next section• Spock best practices• Not an intro to Spock• Not a comprehensive review of all Spock’s features• Spock code examples most useful if you have a basic knowledge of

Spock or mocking/stubbing• For a Spock overview, see Spock references listed at

https://github.com/bwestrich/tdd-spock

Page 22: Westrich spock-assets-gum

© 2015 McWest Corporation 22

Spock Tests as Assets: Best practices, with code examples• Name methods well (NamingTestsSpec)• Use behavioral syntax (UseGivenNotSetupSpec)• Comments on blocks (optional) (UseGivenNotSetupSpec)• Emphasize typical cases (SpecifyClassUnderTestSpec)• Put expected values at end of tables (SpecifyClassUnderTestSpec)• Use double vertical bars to highlight results

(SpecifyClassUnderTestSpec)• Use comments and @Unroll in tables (SpecifyClassUnderTestSpec)• Avoid double trouble (StubsAndMocksSpec)• Fix broken tests (VaCalculateCaloriesFunctionalSpec)• Limit size of tables (SmallerWhereSpec)* class names (camel case capital letters)

Page 23: Westrich spock-assets-gum

© 2015 McWest Corporation 23

Spock Tests as Assets https://github.com/bwestrich/tdd-spock/blob/master/README.md

Page 24: Westrich spock-assets-gum

© 2015 McWest Corporation 24

Testing Effectively

Page 25: Westrich spock-assets-gum

© 2015 McWest Corporation 25

Testing effectively• Types of tests• Finding tests• Writing tests• Running tests• Testing before committing

Page 26: Westrich spock-assets-gum

© 2015 McWest Corporation 26

Types of (automated) testsType What it tests Spock support Comment

Functionalhow system works

from “user’s” perspective

Geb Most importantLowest coverage

Unit details mocks/stubs Fast, funHighest coverage

Integration how details work together

controller web tests*

Usage varies for different projects

Smoke deployments Geb Spot check

* https://github.com/bwestrich/tdd-spock/blob/master/README-MOCKMVC.md

Page 27: Westrich spock-assets-gum

© 2015 McWest Corporation 27

Spock uses same syntax for all test types

Page 28: Westrich spock-assets-gum

© 2015 McWest Corporation 28

Red Green Clean1. Write new or break existing test

2. Fix test

3. Clean (refacto

r)

Page 29: Westrich spock-assets-gum

© 2015 McWest Corporation 29

Don’t trust a test that hasn’t failed-- Kevin Beatty

Page 30: Westrich spock-assets-gum

© 2015 McWest Corporation 30

Using test types: Unit First1. Write/break unit test2. Fix unit test3. Clean test code and tested code4. Write/break integration test (optional)5. Fix integration test6. Clean test code and tested code7. Write/break functional test (optional)8. Fix functional test 9. Clean test code and tested code

Page 31: Westrich spock-assets-gum

© 2015 McWest Corporation 31

Using test types: Functional First1. Write/break functional test (optional)2. Write/break integration test (optional)3. Write/break unit test4. Fix unit test5. Clean test code and tested code6. Fix integration test7. Clean test code and tested code8. Fix functional test 9. Clean test code and tested code

Page 32: Westrich spock-assets-gum

© 2015 McWest Corporation 32

Order of Test Types for Different TasksTask Usual Approach NoteDefect fix FF Developer-reported

defects might use UFNew feature (tools and requirements well understood)

UF Business requested? FF

New feature (when learning technology or requirements)

Whatever approach works (even writing code before tests!)

Feature is not complete until tests pass and refactoring complete

Legend: FF = Functional First, UF = Unit First

Page 33: Westrich spock-assets-gum

© 2015 McWest Corporation 33

Write tests as soon as possible• The sooner you write tests, the better they can help guide your design

• OK: write code, then (before pushing) test code• Better: write tests while you write the tested code• Best: write tests before the tested code.

o Added benefit: verify the test fails before feature written / defect fixed (don’t trust a test that hasn’t failed)

Page 34: Westrich spock-assets-gum

© 2015 McWest Corporation 34

Different projects use different test types

Test type Run duration When runUnit < 1 minute Constantly while

coding, pre-pushIntegration 10 minutes Pre-pushFunctional None n/a

Project: Provide website content for nationwide electronics retailer, no front-end development done by our team.

Page 35: Westrich spock-assets-gum

© 2015 McWest Corporation 35

Different projects use different test types

Test type Run duration When runUnit < 1 minute Constantly while

coding, pre-pushIntegration 1 minute Occasionally while

coding, pre-pushFunctional 10 minutes Pre-push

Project: Departmental app, full-stack development.

Page 36: Westrich spock-assets-gum

© 2015 McWest Corporation 36

Reliable integration and functional tests• Don’t tolerate “false positives”

• Tests that fail for any reason other than defective software• Decrease value of your tests• “Fix broken windows”

• Tips on avoiding “false positives”• @Stepwise• Manage your test data• Extend Geb as needed

Page 37: Westrich spock-assets-gum

© 2015 McWest Corporation 37

Use @Stepwise to guarantee run method order

Page 38: Westrich spock-assets-gum

© 2015 McWest Corporation 38

Manage your test data• Script it!

• SQL, DBUnit, etc.• Periodically refresh all data in test environments • Reserve ranges for testing

• ID numbers (negative IDs? Large IDs?) • Code values• Other special “marking”

• Tests should not change shared data (allows concurrent test runs)

Page 39: Westrich spock-assets-gum

© 2015 McWest Corporation 39

Geb testing of asynchronous JavaScript• Using angular? Try ng-busy to manage asynchronous processing

• Use ng-busy to display a ‘Processing’ message to users while waiting for any http server requests, have tests wait when label is displayed

Page object method

Example code in test

Page 40: Westrich spock-assets-gum

© 2015 McWest Corporation 40

Using test types: Takeaway• All types of tests are an integral part of development• Use the correct test type for the job at hand• Use test types that fit your project• Write tests as soon as possible• Prevent false-positives

• And, of course….. ;-) • Run ALL test types before pushing changes

Page 41: Westrich spock-assets-gum

© 2015 McWest Corporation 41

Keyboard shortcuts• Learn and use them! (pairing?)• OS and IDE specific

• OS: Mac, Linux, Windows• IDE: IntelliJ, Eclipse, nano, emacs, vi, …….• This presentation uses Mac (OSX) and IntelliJ 14.1.4

Page 42: Westrich spock-assets-gum

© 2015 McWest Corporation 42

Finding Tests• Test location

• As close to Class Under Test as possible• Same project, package, name prefix (MyClass and MyClassSpec)• Different source folder

• Keyboard shortcuts (DEMO)• Toggle between class and test: Cmd-Shift-T• Find by name: Cmd-Shift-O

o (type caps to exploit camel case, e.g. MCS finds MyClassSpec)

Page 43: Westrich spock-assets-gum

© 2015 McWest Corporation 43

Writing Tests• Where table keyboard shortcuts (DEMO)

• Column editingo Createo Updateo Delete

• Column formatting: Cmd-Alt-L

Page 44: Westrich spock-assets-gum

© 2015 McWest Corporation 44

Running Tests (IDE)• Keyboard shortcuts (DEMO)

• Ctrl-Shift-R: Run highlighted test• Ctrl-R: Run previously run test

Page 45: Westrich spock-assets-gum

© 2015 McWest Corporation 45

Running Tests (command line)• Create team aliases for common operations for your team’s

languages / frameworks / build systems• Operations

o refresh dependencies, clean, test, run• Languages / frameworks: build systems

o JavaScript/Angular: grunt, gulpo Java/Groovy/Spring Boot: maven, gradle

Page 46: Westrich spock-assets-gum

© 2015 McWest Corporation 46

Running tests command line (DEMO)

Page 47: Westrich spock-assets-gum

© 2015 McWest Corporation 47

Running Tests (command line) (cont.)

• Team aliases• Add to source control • Add directory to execution path• Provide easy ways for team to update (“ea”, “listaliases”)

• Basic example: https://github.com/mcwest/team-aliases• Supports:

Page 48: Westrich spock-assets-gum

© 2015 McWest Corporation 48

Test Before Pushing• The right way: Run all tests (of all types) before pushing (to source

control)• Why it’s hard to do:

• Commands to run tests are arcane, inconsistent, error prone• Tests take long time to run• Tests fail after running long time (waste of time!)• Results hard to find/interpret (just say ‘ok’ or ‘not’)• While waiting, you can’t do ANYTHING else

• How to make the right way easy?

Page 49: Westrich spock-assets-gum

© 2015 McWest Corporation 49

Asynchronous pre-push testing (via script)• Call script something short: e.g. “go”• What script does

• Cleans and builds all components in separate workspace• Runs ALL unit/integration/functional tests and code style checkers• Fails fast (slow tests run last)• Runs in background

o Spawns separate instance of components with dedicated resources (workspace, ports, data, log files, …)

o Audio notification of results (have some fun here!)• Manage same as a team alias (in source control, on execution path)

Page 50: Westrich spock-assets-gum

© 2015 McWest Corporation 50

Before svn commit1. ‘go’, then if errors, fix and refactor 2. ‘svn update’3. if changes, go back to step 1, otherwise ‘svn commit’

Page 51: Westrich spock-assets-gum

© 2015 McWest Corporation 51

Before git push1. ‘go’, then if errors, fix and refactor 2. ‘git commit’3. ‘git smart-pull’ (alias ‘gsp’)4. if changes, go back to step 1, otherwise ‘git push’

• Notes: • Step #2 makes git merges easier to manage by not mixing local changes

and remote changes into same commit• Step #3 uses the excellent git smart-pull add-on, see

https://github.com/mcwest/team-aliases for more info

Page 52: Westrich spock-assets-gum

© 2015 McWest Corporation 52

Asynchronous pre-push testing (other methods)• Team City (JetBrains): not out of the box, need to configure post-

commit hook• Other tools?• Anyone have solutions to share to this?

Page 53: Westrich spock-assets-gum

© 2015 McWest Corporation 53

Testing effectively (review)• Types of tests• Finding tests• Writing tests• Running tests• Testing before committing

Page 54: Westrich spock-assets-gum

© 2015 McWest Corporation 54

TDD in Teams• Pair Programming• Pull Requests• Continuous Integration• Continuous Deployment

Page 55: Westrich spock-assets-gum

© 2015 McWest Corporation 55

Pair Programming• Wonderful way to learn, teach, enjoy TDD/Spock• Very productive• Roles

• Driver (shows new ways to find/write/run/commit tests)• Observer (watches for typos, testing the right thing, next test

type)• Keep both members switching roles

• TDD ping pong: ping pong ping pong ping pong• Other ideas?

• Cautions• Team must want to pair (pre-interview question)• Workspace must be conducive to pairing

Page 56: Westrich spock-assets-gum

© 2015 McWest Corporation 56

Pair Programming Workspace

Page 57: Westrich spock-assets-gum

© 2015 McWest Corporation 57

Pull Requests (PR)• Great compliment to / replacement for pairing

• Does not require workspace re-config• Works with remote teams (but can pair over skype/hangouts/…)• More conducive to some developers’ workstyles than pairing

• TDD and PRs• Submitter must include tests in the PR• Reviewer should run tests in background (using ‘go’) while

reviewing• Cautions

• Requires understanding of source code branching• Commands to create PR’s not trivial

o Set up command line aliases to streamline

Page 58: Westrich spock-assets-gum

© 2015 McWest Corporation 58

Continuous Integration• Trigger build immediately on push (commit hooks preferred over

polling)• Notify team of broken builds

• Emails• Texts• IM/Slack?

• Make broken builds visible• Radiator (Jenkins plugin)

Page 59: Westrich spock-assets-gum

© 2015 McWest Corporation 59

Continuous Deployment• Impossible without automated tests• TDD a great way (the only way) to build automated tests that verify a

system at all levels

Page 60: Westrich spock-assets-gum

© 2015 McWest Corporation 60

Test MantrasMantra -- “a statement or slogan repeated frequently”

• Test the right thing• APIs not internals• Don’t trust a test that hasn’t failed• The right way easy• Tests are assets not afterthoughts

Page 61: Westrich spock-assets-gum

© 2015 McWest Corporation 61

Spock: Specification at all levels

Page 62: Westrich spock-assets-gum

© 2015 McWest Corporation 62

From the smallest unit…

Page 63: Westrich spock-assets-gum

© 2015 McWest Corporation 63

… to detailed interactions …

Page 64: Westrich spock-assets-gum

© 2015 McWest Corporation 64

… to higher level interactions …

Page 65: Westrich spock-assets-gum

© 2015 McWest Corporation 65

… to the user’s view of the system.

Page 66: Westrich spock-assets-gum

© 2015 McWest Corporation 66

The needs of the many outweigh the needs of the few.

Page 67: Westrich spock-assets-gum

© 2015 McWest Corporation 67

ConclusionUsing the techniques and approaches we’ve discussed, automated developer-written tests become less something we do as an afterthought (if at all), and more an asset we demand on our future projects.

Page 68: Westrich spock-assets-gum

© 2015 McWest Corporation 68

Resources• Spock TDD: https://github.com/bwestrich/tdd-spock• TDD cribsheet (JUnit oriented):

https://bitbucket.org/bwestrich/java-tdd• Command line aliases: https://github.com/mcwest/team-aliases

Page 69: Westrich spock-assets-gum

© 2015 McWest Corporation 69

Spock ‘seed art’ credit

Page 70: Westrich spock-assets-gum

© 2015 McWest Corporation 70

Minneapolis ‘seed art’ credit

Page 71: Westrich spock-assets-gum

© 2015 McWest Corporation 71

Spock TDD

Tests as Assets not Afterthoughts

by Brian Westrich, McWest [email protected]