tdd patterns1

37
Amir Barylko - TDD Patterns MavenThought Inc. AMIR BARYLKO TDD PATTERNS FOR .NET DEVELOPERS SDEC 2010 DEVELOPER FOUNDATION TRACK Wednesday, October 13, 2010

Upload: amir-barylko

Post on 11-May-2015

421 views

Category:

Technology


0 download

TRANSCRIPT

Page 1: Tdd patterns1

Amir Barylko - TDD Patterns MavenThought Inc.

AMIR BARYLKOTDD PATTERNS

FOR .NET DEVELOPERSSDEC 2010

DEVELOPER FOUNDATION TRACK

Wednesday, October 13, 2010

Page 2: Tdd patterns1

Amir Barylko - TDD Patterns MavenThought Inc.

WHO AM I?

• Architect

•Developer

•Mentor

• Great cook

• The one who’s entertaining you for the next hour!

Wednesday, October 13, 2010

Page 3: Tdd patterns1

Amir Barylko - TDD Patterns MavenThought Inc.

WHY TDD?

• Test first approach

•Quality driven

• Easy to refactor

• Regression tests as byproduct

• Increase developer’s confidence

Wednesday, October 13, 2010

Page 4: Tdd patterns1

Amir Barylko - TDD Patterns MavenThought Inc.

SETUPTools

AutoMockingMovie Library

Wednesday, October 13, 2010

Page 5: Tdd patterns1

Amir Barylko - TDD Patterns MavenThought Inc.

TOOLS

• Testing framework: NUnit, MbUnit, MSpec, rSpec

• Mocking framework: Rhino Mocks, Moq, TypeMock, nSubstitute

• Test Automation: Scripts that can run the test from the developer computer.

• CI server : Unit test should be run after each commit, integration tests, schedule tests.

• Reports and Notifications: The team should realize right away that the tests are broken (broke the build jar).

Wednesday, October 13, 2010

Page 6: Tdd patterns1

Amir Barylko - TDD Patterns MavenThought Inc.

MOVIE LIBRARY

Wednesday, October 13, 2010

Page 7: Tdd patterns1

Amir Barylko - TDD Patterns MavenThought Inc.

AUTO MOCKING

• Automatic dependency creation for System Under Test

•Dictionary of dependencies to reuse by type

• Faster setup of tests without specifying creation

• Build your own: StructureMap

•Or use MavenThought Testing

•What about too many dependencies?

Wednesday, October 13, 2010

Page 8: Tdd patterns1

Amir Barylko - TDD Patterns MavenThought Inc.

BEFORE AUTOMOCKING

protected IStorage Storage { get; set; }

protected ICritic Critic { get; set }

protected MovieLibrary Sut { get; set; }

public void Setup(){ this.Storage = Mock<IStorage>(); this.Critic = Mock<ICritic>(); this.Sut = new MovieLibrary(this.Storage, this.Critic)}

Define SUT& Dependencies

Initialize each

Wednesday, October 13, 2010

Page 9: Tdd patterns1

Amir Barylko - TDD Patterns MavenThought Inc.

AFTER AUTOMOCKING

public abstract class Specification : AutoMockSpecificationWithNoContract<MovieLibrary>{}

public class When_movie_library_is_created : Specification{ [It] public void Should_do_something_with_critic() { Dep<IMovieCritic>().AssertWasCalled(...); }}

SUT

Dependency

Wednesday, October 13, 2010

Page 10: Tdd patterns1

Amir Barylko - TDD Patterns MavenThought Inc.

PATTERNSOne feature at a time

State CheckBehaviour

Parameters

Dependency InjectionDependency Lookup

DatabaseSmelly Test

Wednesday, October 13, 2010

Page 11: Tdd patterns1

Amir Barylko - TDD Patterns MavenThought Inc.

ONE FEATURE PER TEST

• Easy to approach

• Easy to understand

• Easy to maintain

• Enforce Given, When, Then

Given That(arrange)

When I Run(act)

Then it should ...(assert)

Wednesday, October 13, 2010

Page 12: Tdd patterns1

Amir Barylko - TDD Patterns MavenThought Inc.

XUNIT UNIT TESTING

[TestFixture]public class MovieLibraryTest{ private MockRepository _mockery; private Library _library; private IMovieCritic _critic;

[SetUp] public void BeforeEachTest() { this._mockery = new Mockery(); this._critic = _mockery.Create...; this._library = new Library... }

[TearDown] public void AfterEachTest() { this._library.Clear(); }

[Test] public void WhenXXXX() { Assert.IsEmpty(_library.Contents); }

[Test] public void WhenYYYYAndZZZAndWWWW() { // record, playback, assert }

Wednesday, October 13, 2010

Page 13: Tdd patterns1

Amir Barylko - TDD Patterns MavenThought Inc.

ARRANGE ACT ASSERT

[Test] public void When_Adding_Should_Appear_In_The_Contents() { // Arrange var before = _sut.Contents.Count();

// Act _sut.Add(_movie1);

// Assert Assert.Contains(_sut.Contents, _movie1); Assert.AreEqual(before + 1, _sut.Contents.Count()); }

Wednesday, October 13, 2010

Page 14: Tdd patterns1

Amir Barylko - TDD Patterns MavenThought Inc.

ONE FEATURE MANY SCENARIOS

Feature Specification

When_xxxx.cs

When_yyyy.cs

When_zzzz.cs

Wednesday, October 13, 2010

Page 15: Tdd patterns1

Amir Barylko - TDD Patterns MavenThought Inc.

FOCUS

[Specification]public class When_movie_library_is_cleared : MovieLibrarySpecification{ protected override void WhenIRun() { AddLotsOfMovies();

this.Sut.Clear(); }

[It] public void Should_have_no_movies_in_the_library() { this.Sut.Contents.Should().Be.Empty(); }}

Wednesday, October 13, 2010

Page 16: Tdd patterns1

Amir Barylko - TDD Patterns MavenThought Inc.

CHECK THAT STATE!

• Care about the end state

•Does not validate SUT transitions

• Verify the state agains the expected value

var m = new Library...

Run Test

m.Count.Should(...)

Wednesday, October 13, 2010

Page 17: Tdd patterns1

Amir Barylko - TDD Patterns MavenThought Inc.

WHY CHECK IMPLEMENTATION?

[Specification]

public class When_movie_library_lists_non_violent_movies

: MovieLibrarySpecification

{

[It]

public void Should_call_the_critic()

{

Dep<IMovieCritic>().AssertWasCalled(c => c.IsViolent(...));

}

}

Wednesday, October 13, 2010

Page 18: Tdd patterns1

Amir Barylko - TDD Patterns MavenThought Inc.

EXPECTED STATE

[Specification]

public class When_movie_library_lists_non_violent_movies

: MovieLibrarySpecification

{

[It]

public void Should_return_all_the_non_violent_movies()

{

this._actual.Should().Have.SameSequenceAs(this._expected);

}

}

Wednesday, October 13, 2010

Page 19: Tdd patterns1

Amir Barylko - TDD Patterns MavenThought Inc.

BEHAVIOUR IS EVERYTHING

• Checking the expected behaviour happened

• Uses mock objects

• The behaviour is specified for each mock object

• The expected methods should be called

var m = Mock<...>

m.Stub(...)

m.AssertWasCalled(...)

Run Test

Wednesday, October 13, 2010

Page 20: Tdd patterns1

Amir Barylko - TDD Patterns MavenThought Inc.

HOW ABOUT EVENTS?

•Where is the state?

• Should I create a concrete class?

[It]

public void Should_notify_an_element_was_added()

{

.......????

}

Wednesday, October 13, 2010

Page 21: Tdd patterns1

Amir Barylko - TDD Patterns MavenThought Inc.

ASSERT BEHAVIOR

protected override void GivenThat(){ base.GivenThat();

this._handler = MockIt(this._handler);

this.Sut.Added += this._handler;}

[It]

public void Should_notify_an_element_was_added()

{

var matching = ...;

this._handler.AssertWasCalled(h => h(Arg.Is(this.Sut), matching));}

Wednesday, October 13, 2010

Page 22: Tdd patterns1

Amir Barylko - TDD Patterns MavenThought Inc.

PARAMETERS & FACTORIES

• Avoid duplication and repetition

• Generic Parameters

• Parameters Factories

• Random strings

• Random numbers

[Row(1)][Row(2)]void Method(int arg)

[Factory(...)]void Method(string arg)

void Method([Random]...)

void Method([Random]..., [Factory]...)

[Row(typeof(...))]void Method<T>(...)

Wednesday, October 13, 2010

Page 23: Tdd patterns1

Amir Barylko - TDD Patterns MavenThought Inc.

COMBINE

public When_movie_is_created(

[RandomStrings(Count=5, Pattern="The great [A-Za-z]{8}")] string title,

[Factory("RandomDates")] DateTime releaseDate)

{

this._title = title;

this._releaseDate = releaseDate;

}

Wednesday, October 13, 2010

Page 24: Tdd patterns1

Amir Barylko - TDD Patterns MavenThought Inc.

DEPENDENCY INJECTION

• Remove hardcoded dependencies

• Introduces dependency in the constructor / setter

• Easy to test and maintain

• S O L I D

Initialize dependency

Stub dependency with mock

Assert the mock is returned

Wednesday, October 13, 2010

Page 25: Tdd patterns1

Amir Barylko - TDD Patterns MavenThought Inc.

HARDCODED DEPENDENCIES

public MovieLibrary()

{

this.Critic = new MovieCritic();

this._posterService = new SimplePosterService();

}

How are we going to test it?

Wednesday, October 13, 2010

Page 26: Tdd patterns1

Amir Barylko - TDD Patterns MavenThought Inc.

INJECT DEPENDENCIES

public MovieLibrary(IMovieCritic critic,

IPosterService posterService,

IMovieFactory factory)

: this(critic)

{

this._posterService = posterService;

this._factory = factory;

}

Wednesday, October 13, 2010

Page 27: Tdd patterns1

Amir Barylko - TDD Patterns MavenThought Inc.

DEPENDENCY LOOKUP

• Remove hardcoded dependencies

• Introduces a factory or service locator

• Easy to test and maintain

• S O L I D

Initialize service locator

Stub to return a mock

Assert the mock is returned

Wednesday, October 13, 2010

Page 28: Tdd patterns1

Amir Barylko - TDD Patterns MavenThought Inc.

HARDCODED SERVICE

public void Import(IDictionary<string, DateTime> movies)

{

movies.ForEach(pair => this.Add(new Movie(...)));

}

Hardcoded!!!

Wednesday, October 13, 2010

Page 29: Tdd patterns1

Amir Barylko - TDD Patterns MavenThought Inc.

FACTORY

public void Import(IDictionary<string, DateTime> movies)

{

movies.ForEach(pair => this.Add(this._factory.Create(...)));

}

COULD BE A SERVICE LOCATOR....

Wednesday, October 13, 2010

Page 30: Tdd patterns1

Amir Barylko - TDD Patterns MavenThought Inc.

DATABASE TESTING

• Base class to setup the database

• The test always works with a clean database

• Can be configured to populate data if needed

• To test only DB operations

Create Database

Populate

Retrieve and Assert

Store

Wednesday, October 13, 2010

Page 31: Tdd patterns1

Amir Barylko - TDD Patterns MavenThought Inc.

USE TEMPORARY FILES

protected BaseStorageSpecification()

{

DbFile = Path.GetTempFileName();

}

protected override ISessionFactory CreateSut()

{

var factory = SessionFactoryGateway.CreateSessionFactory(SQLiteConfiguration

.Standard

.UsingFile(DbFile)

.ShowSql(), BuildSchema);

return factory;

}

Wednesday, October 13, 2010

Page 32: Tdd patterns1

Amir Barylko - TDD Patterns MavenThought Inc.

CREATE & POPULATE

private void BuildSchema(Configuration config)

{

// delete the existing db on each run

if (File.Exists(DbFile))

{

File.Delete(DbFile);

}

// export schema

new SchemaExport(config).Create(true, true);

}

Wednesday, October 13, 2010

Page 33: Tdd patterns1

Amir Barylko - TDD Patterns MavenThought Inc.

TEST DB OPERATIONS

[ConstructorSpecification]

public class When_movie_is_created : PersistentMovieSpecification

{

/// <summary>

/// Validates the mapping

/// </summary>

[It]

public void Should_have_the_right_mappings()

{

this.Sut.AutoSession(s =>

new PersistenceSpecification<Movie>(s)

.CheckProperty(p => p.Title, "Space Balls")

.VerifyTheMappings());

}

}

Wednesday, October 13, 2010

Page 34: Tdd patterns1

Amir Barylko - TDD Patterns MavenThought Inc.

OMG: WHAT’S THAT SMELL?

• Setup is too big

• Hard to understand dependencies

•Needs SQL server running with MsQueue and Biztalk

• Code coverage rules!

•Write only tests

• Tests List<T>

• Checking state between calls

• Inspect internals of the class

• Can’t write a test for that

•No automation is possible

Wednesday, October 13, 2010

Page 35: Tdd patterns1

Amir Barylko - TDD Patterns MavenThought Inc.

QUESTIONS?

Wednesday, October 13, 2010

Page 36: Tdd patterns1

Amir Barylko - TDD Patterns MavenThought Inc.

THANK YOU!

• Contact me: [email protected], @abarylko

•Download: http://www.orhtocoders.com/presentations

• Books: The rSpec book, xUnit Patterns.

Wednesday, October 13, 2010

Page 37: Tdd patterns1

Amir Barylko - TDD Patterns MavenThought Inc.

RESOURCES

•NUnit: http://www.nunit.org

• Gallio & MbUnit: http://www.gallio.org

•MavenThought Testing: http://maventcommons.codeplex.com

• Rhino Mocks: http://www.ayende.com

• StructureMap: http://structuremap.sourcefore.com

• TeamCity: http://www.jetbrains.com

Wednesday, October 13, 2010