Upload
amir-barylko
View
421
Download
0
Tags:
Embed Size (px)
Citation preview
Amir Barylko - TDD Patterns MavenThought Inc.
AMIR BARYLKOTDD PATTERNS
FOR .NET DEVELOPERSSDEC 2010
DEVELOPER FOUNDATION TRACK
Wednesday, October 13, 2010
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
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
Amir Barylko - TDD Patterns MavenThought Inc.
SETUPTools
AutoMockingMovie Library
Wednesday, October 13, 2010
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
Amir Barylko - TDD Patterns MavenThought Inc.
MOVIE LIBRARY
Wednesday, October 13, 2010
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
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
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
Amir Barylko - TDD Patterns MavenThought Inc.
PATTERNSOne feature at a time
State CheckBehaviour
Parameters
Dependency InjectionDependency Lookup
DatabaseSmelly Test
Wednesday, October 13, 2010
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
Amir Barylko - TDD Patterns MavenThought Inc.
QUESTIONS?
Wednesday, October 13, 2010
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
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