95
Testing: 1… 2… 3… An Introduction to Developer Testing Will Green [email protected] http://hotgazpacho.org/ @hotgazpacho

An Introduction to Developer Testing

Embed Size (px)

DESCRIPTION

A whirlwind introduction to developer testing, with a .NET flavor

Citation preview

Page 1: An Introduction to Developer Testing

Testing: 1… 2… 3…An Introduction to Developer Testing

Will [email protected]://hotgazpacho.org/@hotgazpacho

Page 2: An Introduction to Developer Testing

CaveatI am Not an Expert

http://www.flickr.com/photos/eprater/2375127206/

Page 3: An Introduction to Developer Testing

I am not Kent Beck

• Father of Extreme Programming

• Pioneer of Software Design Patterns

• Originator of CRC Cards• One of original

signatories of the Agile Manifesto

• Author, JUnit (unit testing framework for Java)

• Author of several books, including Test Driven Development: By Example

• Co-Author: Refactoring: Improving the Design of Existing Code

http://en.wikipedia.org/wiki/Kent_Beck

Page 4: An Introduction to Developer Testing

I am not Ward Cunningham

• Creator of the Wiki• CTO of AboutUs.com• Pioneer of Extreme

Programming• Inventor of FIT

(Framework for Integrated Tests)

http://en.wikipedia.org/wiki/Ward_Cunningham

Page 5: An Introduction to Developer Testing

I am not Martin Fowler

• Chief Scientist at Thoughtworks

• Co-Author: Refactoring: Improving the Design of Existing Code

• Co-Author: Patterns of Enterprise Application Architecture

• Author of several other books

• One of original signatories of the Agile Manifesto

http://en.wikipedia.org/wiki/Martin_Fowler

Page 6: An Introduction to Developer Testing

I am not Robert C. Martin

• Author, Clean Code: A Handbook of Agile Software Craftsmanship

• Author, Agile Principles, Patterns, and Practices in C#

• Author, Agile Software Development: Principles, Patterns and Practices

• Creator of FITNesse(combining FIT with a Wiki)

• One of original signatories of the Agile Manifesto

• Founder and President of Object Mentor, Inc.

http://en.wikipedia.org/wiki/Robert_Cecil_Martin

Page 7: An Introduction to Developer Testing

I amWill Green

• I am an Aspiring Software Craftsman

• Co-host of The Iron Languages Podcasthttp://ironlanguages.net/

• I Read A LOT• I Practice A LOT• I Learn A LOT

http://hotgazpacho.org/

Page 8: An Introduction to Developer Testing

Ready to drink from the fire hose?

http://www.flickr.com/photos/joevans/4292116723/

Page 9: An Introduction to Developer Testing

Don’t Think “Test”To-may-to, To-mah-to…

http://www.flickr.com/photos/rhinoneal/2706246863/sizes/m/

Page 10: An Introduction to Developer Testing

http://twitter.com/ampgt/status/21689847806

Testing as Design

Page 11: An Introduction to Developer Testing

Testing as Design

http://twitter.com/jbogard/statuses/19838298235

Page 12: An Introduction to Developer Testing

Testing as Design

http://twitter.com/venkat_s/status/24480762059

Page 13: An Introduction to Developer Testing

Tests aren’t Tests

“Test” doesn’t describe what is going on

Tests are specification Tests are design Test suites are an artifact of the

design process

Page 14: An Introduction to Developer Testing

TDD: Test Driven Design

Write the code you wish you had Hard to test == Hard to use

Better to find this out now than 2 months from now when you have to change it

Done right, helps you adhere to the Principles of Object Oriented Design

Page 15: An Introduction to Developer Testing

SOLIDLike a Rock

http://www.flickr.com/photos/gustty/2908229462/

Page 16: An Introduction to Developer Testing

Dependency Management

Dependency Management is Hard The single greatest influencer of

software quality The foundation for creating software that

exhibits the qualities we desire

Page 17: An Introduction to Developer Testing

Poorly Managed Dependencies

Lead to code that is Hard to change Fragile Not reusable

Page 18: An Introduction to Developer Testing

Well Managed Dependencies

Lead to code that is Flexible Robust Reusable

Page 19: An Introduction to Developer Testing

Qualities of Software

UNDESIRABLE

Hard to change Fragile Not reusable

DESIRABLE

Easy to change Robust Reusable

Page 20: An Introduction to Developer Testing

Dependency Management and SOLID

SOLID is The foundational set of principles for

managing dependencies Therefor the foundation for creating

software that exhibits the qualities we desire

Page 21: An Introduction to Developer Testing

http://www.lostechies.com/cfs-filesystemfile.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/derickbailey/SOLID_5F00_6EC97F9C.jpg

Page 22: An Introduction to Developer Testing

What is SOLID?

Single Responsibility

Principle

Open Closed Principle

Liskov Substitution

Principle

Interface Segregation

Principle

Dependency Inversion

Principle

Page 23: An Introduction to Developer Testing

http://www.lostechies.com/cfs-filesystemfile.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/derickbailey/SingleResponsibilityPrinciple2_5F00_71060858.jpg

Page 24: An Introduction to Developer Testing

Single Responsibility Principle

A class should have one, and only one, reason to change

http://www.objectmentor.com/resources/articles/srp.pdf

Page 25: An Introduction to Developer Testing

http://www.lostechies.com/cfs-filesystemfile.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/derickbailey/OpenClosedPrinciple2_5F00_2C596E17.jpg

Page 26: An Introduction to Developer Testing

Open Closed Principle

You should be able to extend the behavior of a class, without modifying it

Classes should be open for extension but closed for modification

http://www.objectmentor.com/resources/articles/ocp.pdf

Page 27: An Introduction to Developer Testing

http://www.lostechies.com/cfs-filesystemfile.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/derickbailey/LiskovSubtitutionPrinciple_5F00_52BB5162.jpg

Page 28: An Introduction to Developer Testing

Liskov Substitution Principle

Derived classes must be substitutable for their base classes

http://www.objectmentor.com/resources/articles/lsp.pdf

Page 29: An Introduction to Developer Testing

http://www.lostechies.com/cfs-filesystemfile.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/derickbailey/InterfaceSegregationPrinciple_5F00_60216468.jpg

Page 30: An Introduction to Developer Testing

Interface Segregation Principle

Make fine-grained interfaces that are client-specific

http://www.objectmentor.com/resources/articles/isp.pdf

Page 31: An Introduction to Developer Testing

http://www.lostechies.com/cfs-filesystemfile.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/derickbailey/DependencyInversionPrinciple_5F00_0278F9E2.jpg

Page 32: An Introduction to Developer Testing

Dependency Inversion Principle

Depend on abstractions, not on specific implementations

http://www.objectmentor.com/resources/articles/dip.pdf

Page 33: An Introduction to Developer Testing

Test Driven DesignThe Path to Success: 3 Simple Rules

http://www.flickr.com/photos/stuckincustoms/4070581709/

Page 34: An Introduction to Developer Testing

Rule #1

You are not allowed to write any production code unless it is to make a failing unit test pass.

Page 35: An Introduction to Developer Testing

Rule #2

You are not allowed to write any more of a unit test than is sufficient to fail; and compilation failures are failures.

Page 36: An Introduction to Developer Testing

Rule #3

You are not allowed to write any more production code than is sufficient to pass the one failing unit test.

Page 37: An Introduction to Developer Testing

The Flow of Test Driven Design

1. Write a Test2. Watch Test Fail3. Write Code4. Watch Test Pass5. Refactor6. See step 1

http://gamesfromwithin.com/when-is-it-ok-not-to-tdd

Page 38: An Introduction to Developer Testing

TDD Demo!

Fibonacci Number Generator Sequence of numbers

First two numbers are 0 and 1 Each subsequent number is the sum of

the two previous numbers 0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144,

Page 39: An Introduction to Developer Testing

How To Test

http://www.flickr.com/photos/modestchanges/3214701196/

Page 40: An Introduction to Developer Testing

An Example

Page 41: An Introduction to Developer Testing

Test Naming

Method being tested Conditions Expected Outcome

Page 42: An Introduction to Developer Testing

Testing Pattern

Arrange, Act, Assert Separates what is being tested from

the setup and verification steps Makes some Test Smells more

obvious Assertions mixed in with “Act” code. Test methods that try to test too much at

once

Page 43: An Introduction to Developer Testing

Arrange

Arrange all necessary preconditions and inputs

Page 44: An Introduction to Developer Testing

Act

Act on the object or method under test

Page 45: An Introduction to Developer Testing

Assert

Assert that the expected results have occurred

Page 46: An Introduction to Developer Testing

Things to Remember

Triple A Take Small Steps Run tests after every change Tests are Code; maintain them!

Page 47: An Introduction to Developer Testing

Test Doubles

http://www.flickr.com/photos/herbstkind/3791698698/

Page 48: An Introduction to Developer Testing

Mock Repository?

Mock? Stub? What is this?

Page 49: An Introduction to Developer Testing

Test Doubles

Think “stunt double” Replacement for a Production object

for testing purposes There are many types of Test

Doubles, each with its own purpose

Page 50: An Introduction to Developer Testing

Dummy Objects

Passed around but never used Simply to fill parameter lists

Page 51: An Introduction to Developer Testing

Fake Objects

Have working implementations Usually just enough for them to work in

the context of the specific test However, not suitable for Production

E.g. In-Memory Database

Page 52: An Introduction to Developer Testing

Stubs

Provide canned answers to SUT Usually don’t respond to anything

more than what was programmed for the context of the test

Page 53: An Introduction to Developer Testing

Spies

Stubs that record information on how they were called

Allows inspection for Assertion Example

Email Service that records the messages it was sent (without actually sending them)

Page 54: An Introduction to Developer Testing

Mocks

Pre-programmed with expectations Specify how they should be called by

the SUT Throws an exception if they receive a

call they were not expecting Checked during the Assert to ensure

they got all the calls they were expecting

Page 55: An Introduction to Developer Testing

RefactoringYou could do that better…

http://www.flickr.com/photos/29108968@N06/2852038148/

Page 56: An Introduction to Developer Testing

Why Refactoring?

Improve human readability of code Reduce the complexity in order to

improve maintainability Create a more expressive internal

structure

It’s about DESIGN!!

Page 57: An Introduction to Developer Testing

What is Refactoring?

A disciplined technique for restructuring an existing body of code

Altering code’s internal structure without changing its external behavior

A series of small steps that do very little on their own

Risk of change is mitigated by running automated tests after each step

Page 58: An Introduction to Developer Testing

Refactoring is NOT

An undisciplined technique Making changes to code that

change its external behaviorOne giant step Done without a safety net of

automated tests

Page 59: An Introduction to Developer Testing

You Are Not Refactoring

If you are doing any of those things, your are not refactoring.

You’re just changing things willy-nilly.

http://www.flickr.com/photos/brymo/2807243701/

Page 60: An Introduction to Developer Testing

How NOT to TestYeah, don’t do that

http://www.flickr.com/photos/bobcatnorth/1199505016/

Page 61: An Introduction to Developer Testing

Test Smells

Things that make you go “that just ain’t right” Code Smells Test Smells Project Smells

Most of what follows is summarized from xunitpatterns.com/Test%20Smells.html the book XUnit Test Patterns:

Refactoring Test Code

Page 62: An Introduction to Developer Testing

Test Smells – Code Smells

Smells that are found while looking at test code

Obscure Test Conditional Test Logic Hard-to-Test Code Test Code Duplication Test Logic in Production

Page 63: An Introduction to Developer Testing

Obscure Test

There is trouble understanding what behavior a test is verifying too much or too little information in the

test method Possible Solutions

Keep tests small and focused Do not depend on external resources

(files, databases, web services, etc.)

Page 64: An Introduction to Developer Testing

Conditional Test Logic

Hard to know exactly what a test is going to do when it really matters conditional logic to handle when SUT

fails to return valid data Loops to verify contents of collections Conditionals to verify complex objects

Possible Solutions Custom Assertion Methods

Page 65: An Introduction to Developer Testing

Hard to Test Code

Code is difficult to test Highly Coupled Code Asynchronous Code Untestable Test Code

Possible Solutions Reduce coupling by using TDD and

adhering to SOLID principles Use Test Doubles to isolate the SUT

Page 66: An Introduction to Developer Testing

Test Code Duplication

The same code is repeated many times Cut-and-Paste Code Reuse Reinventing the Wheel

Possible Solutions Refactor your test code to create Utility

Methods

Page 67: An Introduction to Developer Testing

Test Logic in Production

Production code contains logic that should only be exercised during tests Conditional logic “For Tests Only” Test Dependency in Production Test-Specific Equality

Possible Solutions Test-specific sub-classes of SUT Manage Test Dependencies Custom Assertions

Page 68: An Introduction to Developer Testing

Test Smells – Behavior Smells

Smells that jump out at you while running tests

Assertion Roulette Erratic Test Fragile Test Frequent Debugging Manual Intervention Slow Tests

Page 69: An Introduction to Developer Testing

Assertion Roulette

Hard to tell which of several assertions in the same test caused the test to fail Test tries to verify too much Assertions with unclear failure messages

Possible Solutions One logical assertion per test Include a failure message for the assertion Use a GUI test runner

Page 70: An Introduction to Developer Testing

Erratic Test

One or more test pass or fail intermittently Tests depend on each other Resource Leakage / Scarcity Shared state Using different/random values for each test run

Possible Solutions Use a fresh fixture for each test Clean up after yourself Use Database sandboxes or a Fake Database

Page 71: An Introduction to Developer Testing

Fragile Test

A test fails to compile or run when the SUT is changed in ways that do not affect the part the test is exercising Data Sensitivity Over-specifying behavior Context Sensitivity

Possible Solutions Do not depend on a database Encapsulate setup behind Creation Methods Abstract away dependencies (including Time)

Page 72: An Introduction to Developer Testing

Frequent Debugging

Manual debugging is required to determine the cause of most test failures

Caused by Lack of Defect Localization (missing

tests) Infrequent Test Runs

Possible Solutions Only create behavior after a failing test

case Runs tests as part of Continuous

Integration builds

Page 73: An Introduction to Developer Testing

Manual Intervention

A test requires a person to do some manual action each time it is run, or verify results manually Lack of attention to automated test fixture setup Test is not self-checking Test conditions that are hard to generate

programmatically Possible Solutions

Invest in automating test setup Use Assertion Methods Use Test stubs to simulate test conditions

Page 74: An Introduction to Developer Testing

Slow Tests

Tests take a long time to run Interaction with external resources (Databases,

File Systems, Web Services) Heavy Test fixture rebuilds for every test Asynchronous Test / Explicit delays in the test Too many tests

Possible Solutions Abstract away database, file system, web services Use an immutable shared fixture Separate event from the behavior it executes Run a fast subset more, and the entire suite less

Page 75: An Introduction to Developer Testing

Test Smells – Project Smells

Smells that a project manager can watch out for

Buggy Tests Developers Not Writing Tests High Test Maintenance Cost Production Bugs

Page 76: An Introduction to Developer Testing

Buggy Tests

Bugs are regularly found in automated tests Fragile Tests Obscure Tests Hard to Test Code

Possible Solutions Learn to write tests properly Refactor legacy code to make testing easier

& more robust Use TDD

Page 77: An Introduction to Developer Testing

Developers Not Writing Tests

The Usual Excuses Not Enough Time Hard to Test Code Wrong Test Automation Strategy

Possible Solutions Learn & Practice ▪ writing tests takes less time as you become

more familiar with doing it

Page 78: An Introduction to Developer Testing

High Test Maintenance Cost

Too much time is spent maintaining tests Fragile Tests Obscure Tests Hard to Test code

Possible Solutions Learning good Test Automation Practicing TDD

Page 79: An Introduction to Developer Testing

Production Bugs

Too many bugs found during formal test or in production Infrequently Run Tests Untested Code Missing Unit Tests Lost Tests

Possible Solutions Speed up test suite Use TDD Write tests to cover untested code Ensure all tests are part of some suite that is run

regularly

Page 80: An Introduction to Developer Testing

.NET Testing Tools

http://www.flickr.com/photos/booleansplit/2376359338/

Page 81: An Introduction to Developer Testing

Testing Frameworks

NUnit, MBUnit, XUnit.net Testing frameworks in the xUnit tradition Assertion Engine with syntactical sugar

on top

Page 82: An Introduction to Developer Testing

Support Libraries

Object Factories NBuilder

Test Doubles / Isolation Frameworks Hand-rolled mock objects Rhino Mocks Moq NMock EasyMock.NET Typemock Isolator Telerik Just Mock

Page 83: An Introduction to Developer Testing

Test Runners

NUnit command line NUnit GUI TestDriven.NET & Visual Nunit

Addins for Visual Studio JetBrains ReSharper or DevExpress

CodeRush Integrates with Visual Studio test status next to the test method in the editor

JetBrains TeamCity Continuous Integration server

Page 84: An Introduction to Developer Testing

Test Guidance

Pair Programming (Dev and QA) Code Reviews Automated Tools

Typemock Test Lint

Page 85: An Introduction to Developer Testing

Resources

http://www.flickr.com/photos/44442915@N00/3467438742/

Page 86: An Introduction to Developer Testing

Agile Principles, Patterns, and Practices in C#

Robert C. MartinMicah Martin

Page 87: An Introduction to Developer Testing

Working Effectively with Legacy Code

Michael Feathers

Page 88: An Introduction to Developer Testing

Refactoring: Improving the Design of Existing Code

Martin FowlerKent BeckJohn BrantWilliam OpdykeDon Roberts

Page 89: An Introduction to Developer Testing

The Art of Unit Testing with Examples in C#

Roy Osherove

Page 90: An Introduction to Developer Testing

Growing Object-Oriented Software, Guided by Tests

Steve FreemanNat Pryce

Page 91: An Introduction to Developer Testing

Testing ASP.NET Web Applications

Jeff McWherterBen Hall

Page 92: An Introduction to Developer Testing

MSDN Magazine Articles

June 2008 – Patterns in Practice: The Open Closed Principlehttp://msdn.microsoft.com/en-us/magazine/cc546578.aspx

October 2008 – Patterns in Practice: Cohesion and Couplinghttp://msdn.microsoft.com/en-us/magazine/cc947917.aspx

December 2008 – Patterns in Practice: Design for Testabilityhttp://msdn.microsoft.com/en-us/magazine/dd263069.aspx

September 2007 – Unit Testing: Exploring the Continuum of Test Doubleshttp://msdn.microsoft.com/en-us/magazine/cc163358.aspx

Page 93: An Introduction to Developer Testing

Videos

TDD with Kent Beckhttp://www.pragprog.com/screencasts/v-kbtdd/test-driven-development

Test First and Test Driven conversations with Corey Haines and JB Rainsbergerhttp://programmingtour.blogspot.com/2009/07/test-first-and-test-driven-conversation.html

Moving Specificity Towards the Tests with Corey Haines and JB Rainsbergerhttp://programmingtour.blogspot.com/2009/08/moving-specificity-towards-tests-with.html

Codemanship’s Videos with Jason Gormanhttp://www.youtube.com/user/parlezuml

TekPub Concepts serieshttp://tekpub.com/production/concepts

Page 94: An Introduction to Developer Testing

Podcasts

Hanselminutes Podcast 145 - SOLID Principles with Uncle Bob - Robert C. Martinhttp://www.hanselminutes.com/default.aspx?showID=163

Hanselminutes Podcast 150 – Uncle Bob Martin: SOLID: This Time With Feelinghttp://www.hanselminutes.com/default.aspx?showID=168

Hanselminutes Podcast 146 – Test Driven Development is Design – The Last Word on TDD with Scott Bellwarehttp://www.hanselminutes.com/default.aspx?showID=164

Hanselminutes Podcast 31 – Test Drivenhttp://www.hanselminutes.com/default.aspx?showID=42

Coding QA Podcast 41 – iPhone TDDhttp://codingqa.com/index.php?post_id=622464

Software Engineering Radio Podcast 155 - Johannes Link & Lasse Koskela on TDDhttp://www.se-radio.net/2010/02/episode-155-johannes-link-lasse-koskela-on-tdd/

Page 95: An Introduction to Developer Testing

Web Sites

The Principles of Object Oriented Designhttp://butunclebob.com/ArticleS.UncleBob.PrinciplesOfOod

xUnit Test Patternshttp://xunitpatterns.com/

Object Mentor Bloghttp://blog.objectmentor.com/

Martin Fowler’s Bloghttp://martinfowler.com/bliki/

Roy Osherove’s Bloghttp://weblogs.asp.net/ROsherove/