changing your mindset: getting started with test-driven development

45
Changing Your Mindset Patrick Reagan Director, Application Development [email protected] Getting Started With Test-Driven Development

Upload: viget-labs

Post on 19-Jan-2015

4.719 views

Category:

Technology


2 download

DESCRIPTION

Patrick Reagan introduces the concept of Test-Driven development with code examples and gives some lessons learned from experience in the field.

TRANSCRIPT

Page 1: Changing Your Mindset: Getting Started With Test-Driven Development

Changing Your Mindset

Patrick Reagan

Director, Application Development

[email protected]

Getting Started With Test-Driven Development

Page 2: Changing Your Mindset: Getting Started With Test-Driven Development

Changing Your MindsetGetting Started With Test-Driven Development September 7th, 2007

Overview

Testing Process

Test::Unit Introduction

Code Example: GoogleRank

Testing Pitfalls

Coverage Analysis

Next Steps

Page 3: Changing Your Mindset: Getting Started With Test-Driven Development

Changing Your MindsetGetting Started With Test-Driven Development September 7th, 2007

Test-Driven Development is the process of testing the behavior of

non-existent objects

Page 4: Changing Your Mindset: Getting Started With Test-Driven Development

Changing Your MindsetGetting Started With Test-Driven Development September 7th, 2007

Testing Cycle

WriteFailing Test

Write Code

VerifySuccess

Refactor

Page 5: Changing Your Mindset: Getting Started With Test-Driven Development

Changing Your MindsetGetting Started With Test-Driven Development September 7th, 2007

Why Test First?

No untested code is written

Start with higher code coverage

Rapid feedback

Build your regressions as you go

Page 6: Changing Your Mindset: Getting Started With Test-Driven Development

Changing Your MindsetGetting Started With Test-Driven Development September 7th, 2007

Anatomy of a (Test::Unit) Test Case

Test case

Test setup(run every test)

Test

Assertion

Page 7: Changing Your Mindset: Getting Started With Test-Driven Development

Changing Your MindsetGetting Started With Test-Driven Development September 7th, 2007

Naming Conventions

Method to test

Parameters / Input

Expected behavior(should ...)

Page 8: Changing Your Mindset: Getting Started With Test-Driven Development

Changing Your MindsetGetting Started With Test-Driven Development September 7th, 2007

Basic Assertions assert

assert_equal / assert_not_equal

assert_nil / assert_not_nil

assert_match / assert_no_match

assert_raise / assert_nothing_raised

Page 9: Changing Your Mindset: Getting Started With Test-Driven Development

Changing Your MindsetGetting Started With Test-Driven Development September 7th, 2007

Code ExampleClass that retrieves Google results

Retrieves only the top 10 URLs

URL encodes provided search terms

Makes an HTTP connection to Google

Raises an exception when unavailable

Page 10: Changing Your Mindset: Getting Started With Test-Driven Development

Changing Your MindsetGetting Started With Test-Driven Development September 7th, 2007

Start Small

test_google_rank_should_exist(GoogleRankTest):Exception raised: Class: <NameError>Message: <"uninitialized constant GoogleRankTest::GoogleRank">

1 tests, 0 assertions, 1 failures, 0 errors

1 tests, 0 assertions, 0 failures, 0 errors

Page 11: Changing Your Mindset: Getting Started With Test-Driven Development

Changing Your MindsetGetting Started With Test-Driven Development September 7th, 2007

Simplest Thing That Works

test_parse_with_empty_document_should_return_empty_array(GoogleRankTest):NoMethodError: undefined method `parse' for GoogleRank:Class

1 tests, 0 assertions, 0 failures, 1 errors

test_parse_with_empty_document_should_return_empty_array(GoogleRankTest):NoMethodError: undefined method `parse' for GoogleRank:Class

1 tests, 0 assertions, 0 failures, 1 errors

Class method

Instance method

Page 12: Changing Your Mindset: Getting Started With Test-Driven Development

Changing Your MindsetGetting Started With Test-Driven Development September 7th, 2007

Simplest Thing That Actually Works

2 tests, 1 assertions, 0 failures, 0 errors

Page 13: Changing Your Mindset: Getting Started With Test-Driven Development

Changing Your MindsetGetting Started With Test-Driven Development September 7th, 2007

Use a Canned Data Set

test_parse_with_sample_document_should_return_list_of_urls<["http://blog.viget.com/", ..... > expected but was <[]>.

1 tests, 1 assertions, 1 failures, 0 errors

Sample markupfrom Google search

Page 14: Changing Your Mindset: Getting Started With Test-Driven Development

Changing Your MindsetGetting Started With Test-Driven Development September 7th, 2007

Use a Canned Data Set

1 tests, 1 assertions, 0 failures, 0 errors

Page 15: Changing Your Mindset: Getting Started With Test-Driven Development

Changing Your MindsetGetting Started With Test-Driven Development September 7th, 2007

Running Regressions

test_parse_with_empty_document_should_return_empty_array(GoogleRankTest):NoMethodError: undefined method `[]' for nil:NilClass

3 tests, 1 assertions, 0 failures, 1 errors

results.nil? == true

Page 16: Changing Your Mindset: Getting Started With Test-Driven Development

Changing Your MindsetGetting Started With Test-Driven Development September 7th, 2007

Fix Regressions

3 tests, 2 assertions, 0 failures, 0 errors

Page 17: Changing Your Mindset: Getting Started With Test-Driven Development

Changing Your MindsetGetting Started With Test-Driven Development September 7th, 2007

Code ExampleClass that retrieves Google results

Retrieves only the top 10 URLs

URL encodes provided search terms

Makes an HTTP connection to Google

Raises an exception when unavailable

Page 18: Changing Your Mindset: Getting Started With Test-Driven Development

Changing Your MindsetGetting Started With Test-Driven Development September 7th, 2007

Retrieve Internal State

NameError: uninitialized constant GoogleRankTest::ERB

Inspect instance variable

Page 19: Changing Your Mindset: Getting Started With Test-Driven Development

Changing Your MindsetGetting Started With Test-Driven Development September 7th, 2007

Retrieve Internal State

test_new_should_encode_supplied_keywords(GoogleRankTest):ArgumentError: wrong number of arguments (1 for 0)

1 tests, 0 assertions, 0 failures, 1 errors

Page 20: Changing Your Mindset: Getting Started With Test-Driven Development

Changing Your MindsetGetting Started With Test-Driven Development September 7th, 2007

Retrieve Internal State

1 tests, 1 assertions, 0 failures, 0 errors

4 tests, 3 assertions, 0 failures, 0 errors

Page 21: Changing Your Mindset: Getting Started With Test-Driven Development

Changing Your MindsetGetting Started With Test-Driven Development September 7th, 2007

Refactor Test Duplication

4 tests, 3 assertions, 0 failures, 0 errors

Page 22: Changing Your Mindset: Getting Started With Test-Driven Development

Changing Your MindsetGetting Started With Test-Driven Development September 7th, 2007

Testing Encoding

test_new_should_assign_url_with_base_and_encoded_keywords(GoogleRankTest):NameError: uninitialized constant GoogleRank::BASE_URL

1 tests, 0 assertions, 0 failures, 1 errors

Page 23: Changing Your Mindset: Getting Started With Test-Driven Development

Changing Your MindsetGetting Started With Test-Driven Development September 7th, 2007

Testing Encoding

1 tests, 1 assertions, 0 failures, 0 errors

5 tests, 4 assertions, 0 failures, 0 errors

Page 24: Changing Your Mindset: Getting Started With Test-Driven Development

Changing Your MindsetGetting Started With Test-Driven Development September 7th, 2007

Code ExampleClass that retrieves Google results

Retrieves only the top 10 URLs

URL encodes provided search terms

Makes an HTTP connection to Google

Raises an exception when unavailable

Page 25: Changing Your Mindset: Getting Started With Test-Driven Development

Changing Your MindsetGetting Started With Test-Driven Development September 7th, 2007

“Mock objects are simulated objects that mimic the behavior of real objects in controlled ways”

- Wikipedia

Page 26: Changing Your Mindset: Getting Started With Test-Driven Development

Changing Your MindsetGetting Started With Test-Driven Development September 7th, 2007

Mocks and Stubs

Remove external dependencies

Create known state

Focus tests on specific code paths

Page 27: Changing Your Mindset: Getting Started With Test-Driven Development

Changing Your MindsetGetting Started With Test-Driven Development September 7th, 2007

Mocha to Stub Net::HTTP

Implementation will useNet::HTTP#get

test_retrieve_content_should_set_content(GoogleRankTest):NoMethodError: undefined method `retrieve_content' for #<GoogleRank:0x104053c>

1 tests, 0 assertions, 0 failures, 1 errors

Page 28: Changing Your Mindset: Getting Started With Test-Driven Development

Changing Your MindsetGetting Started With Test-Driven Development September 7th, 2007

Mocha to Stub Net::HTTP

6 tests, 5 assertions, 0 failures, 0 errors

Page 29: Changing Your Mindset: Getting Started With Test-Driven Development

Changing Your MindsetGetting Started With Test-Driven Development September 7th, 2007

No Network? Oops!

$ irb --prompt simple>> gr = GoogleRank.new('rails')=> #<GoogleRank:0x54c89c @encoded_keywords="rails", @url="http://www.google.com/search?q=rails">>> gr.retrieve_contentSocketError: getaddrinfo: No address associated with nodename

Page 30: Changing Your Mindset: Getting Started With Test-Driven Development

Changing Your MindsetGetting Started With Test-Driven Development September 7th, 2007

Replicate Real-Word Conditions

test_retrieve_content_when_connection_fails_should_set_content_to_nil(GoogleRankTest):SocketError: SocketError

1 tests, 0 assertions, 0 failures, 1 errors

Expected failure

Page 31: Changing Your Mindset: Getting Started With Test-Driven Development

Changing Your MindsetGetting Started With Test-Driven Development September 7th, 2007

Dealing With Failure

7 tests, 6 assertions, 0 failures, 0 errors

Page 32: Changing Your Mindset: Getting Started With Test-Driven Development

Changing Your MindsetGetting Started With Test-Driven Development September 7th, 2007

Code ExampleClass that retrieves Google results

Retrieves only the top 10 URLs

URL encodes provided search terms

Makes an HTTP connection to Google

Raises an exception when unavailable

Page 33: Changing Your Mindset: Getting Started With Test-Driven Development

Changing Your MindsetGetting Started With Test-Driven Development September 7th, 2007

Dealing With Even More Failure

test_retrieve_content_when_connection_fails_should_raise_exception_and_set_content_to_nil(GoogleRankTest)<GoogleRank::ConnectionError> exception expected but none was thrown.

test_retrieve_content_with_failure_should_raise_exception(GoogleRankTest)<GoogleRank::ConnectionError> exception expected but wasClass: <NoMethodError> Message: <"undefined method `closed?' for nil:NilClass">

7 tests, 6 assertions, 2 failures, 0 errors

Page 34: Changing Your Mindset: Getting Started With Test-Driven Development

Changing Your MindsetGetting Started With Test-Driven Development September 7th, 2007

Handling Unsuccessful Requests

8 tests, 8 assertions, 0 failures, 0 errors

Page 35: Changing Your Mindset: Getting Started With Test-Driven Development

Changing Your MindsetGetting Started With Test-Driven Development September 7th, 2007

Testing Pitfalls

Things to avoid

Over-mocking

Invalid mocks

Testing library code

“Assertion-heavy” tests

Non-descriptive test names

Page 36: Changing Your Mindset: Getting Started With Test-Driven Development

Changing Your MindsetGetting Started With Test-Driven Development September 7th, 2007

Testing Pitfalls

Should test parsing

HTTPResponse#content does not exist

Page 37: Changing Your Mindset: Getting Started With Test-Driven Development

Changing Your MindsetGetting Started With Test-Driven Development September 7th, 2007

Testing Pitfalls

Use secondary test to verify

Expected behavior?

Page 38: Changing Your Mindset: Getting Started With Test-Driven Development

Changing Your MindsetGetting Started With Test-Driven Development September 7th, 2007

Coverage Analysis

Shows ‘tested’ code

Indication of when to stop

Can present a false impression

Page 39: Changing Your Mindset: Getting Started With Test-Driven Development

Changing Your MindsetGetting Started With Test-Driven Development September 7th, 2007

Coverage With RCov

Exception-prone

Page 40: Changing Your Mindset: Getting Started With Test-Driven Development

Changing Your MindsetGetting Started With Test-Driven Development September 7th, 2007

Next Steps?

Rake - Rake::TestTask

Mock expectations as tests

Testing Macros

Page 41: Changing Your Mindset: Getting Started With Test-Driven Development

Changing Your MindsetGetting Started With Test-Driven Development September 7th, 2007

Rake::TestTask Example

$ rake -Trake test:all # Run tests for all

Page 42: Changing Your Mindset: Getting Started With Test-Driven Development

Changing Your MindsetGetting Started With Test-Driven Development September 7th, 2007

Expectations as Tests

attr_accessor :contentcalled once

Page 43: Changing Your Mindset: Getting Started With Test-Driven Development

Changing Your MindsetGetting Started With Test-Driven Development September 7th, 2007

Testing Macros

Page 44: Changing Your Mindset: Getting Started With Test-Driven Development

Changing Your MindsetGetting Started With Test-Driven Development September 7th, 2007

ResourcesTest::Unit

http://ruby-doc.org/stdlib

Mocha http://mocha.rubyforge.org

RCov http://eigenclass.org/hiki/rcov

Rake http://rake.rubyforge.org

How to Test Validations (Expectations as Tests) http://relevancellc.com/2007/7/16/how-to-test-validations-part-4

Testing Macros http://www.extendviget.com

Page 45: Changing Your Mindset: Getting Started With Test-Driven Development

Changing Your MindsetGetting Started With Test-Driven Development September 7th, 2007

Slideshttp://www.slideshare.net/viget

Bloghttp://blog.viget.comhttp://www.sneaq.net

[email protected]