Practical Unit-Testing in .NET

Document Sample
Practical Unit-Testing in .NET
Shared by: Andrey Shchekin
Stats
views:
140
posted:
12/3/2009
language:
English
pages:
59
Enterprise development (in .NET), Day 6









Practical

Unit-Testing



Andrey Shchekin

http://ashmind.com

Sankt-Petersburg, 2009



Images © Mattahan Productions, Inc | http://mattahan.deviantart.com/ | http://mattahan.insocada.com/

Why

Complex systems









are hard to change

You can not prevent it. But tests

help to find problems.



In time.

Why tests?

Fast feedback on new code

Safeguards for old code

Exploration for external code



Like a personal tester, for free

You already do manual tests



Automatic = manual +

1. fast feedback

2. no regression

3. simple coverage

1 000 tests = 1 000 bugs not in

the current version





Code is no longer a

minefield

What

Unit

Functional

Integration

Acceptance Tests

Performance

Load

Stress

Unit tests

Written by developers

On smallest units of code

On functionality



Independent



Repeatable

Unit tests are just some

methods run by a tool.

Code

[TestFixture]

public class Int32Test {

[Test]

public void TestParse() {

var result = int.Parse("5");



Assert.AreEqual(5, result);

}

}

Tool

Unit Test Magic

1. Attributes

2. Assertions

3. Mocks

Attributes



[TestFixture] == [TestClass]

[Test] == [TestMethod]



// other:

[Ignore]

[ExpectedException]

[SetUp] && [TearDown]

Assertions



[Test]

public void TestAverage() {

var result =

Mathematics.Average(5, 10, 2, 7);



Assert.AreEqual(6, result);

}

Assertions



Assert.AreEqual(…)

Assert.AreSame(…)

Assert.Between(…)

Assert.LowerThan(…)

Assert.IsNotNull(…)

Assert.IsFalse(…)







No magic: they just throw AssertionException().

How

Good test / Bad test

Name-based guess.



Bad

TestProcessOrder



Good

TestProcessOrderCalculatesTotalValueCorrectly

TestProcessOrderNotifiesCustomer

TestProcessOrderChangesOrderStatusToProcessed

Test-Driven Development

1. Write new business code only when an

automated test has failed.

2. Eliminate any duplication that you find.



Kent Beck

Test-Driven Development









red green refactor

Guidelines

Always add a test for a bug, before fixing it.

When touching legacy code, start with tests.

Use TDD for complex stuff (ex: regexps).



Be simple.

Be focused (assert one thing).



Run tests! Do it often.

Good tests require

Separation of Concerns

Single Responsibility Principle



Each class should do just one thing.

Test Frameworks

NUnit

Gallio (MbUnit)

VS UT Framework

xUnit.Net

NUnit

First UT framework for .NET.

Has all basic features.



Slow to evolve.









http://www.nunit.org

Gallio (MbUnit)

Might be the best testing framework.

Highlights:

1. Row testing

2. Type testing

3. Parallel testing

4. …









http://www.mbunit.com

Collection Assertions



[Test]

public void TestListAdd()

{

var list = new List();

list.Add(3);

list.Add(5);



Assert.AreElementsEqual(new[] {3, 5}, list);

}

Exception Assertions



[Test]

public void TestDictionatyThrowsKeyNotFoundWhenNotFound()

{

var dictionary = new Dictionary();



Assert.Throws(

() => dictionary["nosuchkey"]

);

}

Row Testing



[Test]

[Row(5, 10, 3, 10)]

[Row(-3, -5, 0, 0)]

public void TestMaximum (

int first, int second, int third, int expected

)

{

var result =

Mathematics.Maximum(first, second, third);



Assert.AreEqual(expected, result);

}

VS UT Framework

Microsoft’s testing framework.

Not extensible, no [RowTest].



Uses [TestClass], [TestMethod].



Has good integration with Visual Studio.







http://msdn2.microsoft.com/en-us/library/ms182409(VS.80).aspx

xUnit.NET

New project by the creator of NUnit.

Workflow changes.

No [SetUp] and [TearDown]

Different attributes



Might be good replacement for MbUnit.







http://www.codeplex.com/xunit

Mocking

State testing

?



?



Is the resulting data correct?

Behavior testing



?





Was there the call we expected?

Nice Architecture







Business Rules



Data Access User Interface

Repositories

Business Rules

Mock objects Business Rules

class Database {

double GetSalary(int id);

int GetLengthOfWork(int id);

}









class Calculator {

double Calculate13thSalary(int id);

}

class Database : IDatabase

interface IDatabase {

double GetSalary(int id);

int GetLengthOfWork(int id);

}









class Calculator {

Calculator(IDatabase database);

double Calculate13thSalary(int id);

}

Mock Types

Static

hand-written

auto-generated in code



Dynamic

auto-generated at runtime

Dynamic Mock Advantages

Mocking selected methods

Built-in verification system

Test-level setup





Less code!

Setup

[Test]

[Row(2000, 2, 800)]

[Row(1000, 3, 600)]

public void TestCalculateReturnsExpectedResult(

double salary, int length, double expected

)

{

var testId = 1;



var mock = new Mock();

mock.Setup(x => x.GetSalary(testId))

.Returns(salary);



mock.Setup(x => x.GetLengthOfWork(testId))

.Returns(length);



var result = new Calculator(mock.Object).Calculate13thSalary(testId);

Assert.AreEqual(expected, result, 0.01);

}

Setup

mock.Setup(x => x.GetSalary())

.Returns(salary);



mock.Setup(x => x.GetLengthOfWork())

.Returns(lengthOfWork);

Mocking: 3A workflow

Arrange



Act



Assert

Arrange

var mock = new Mock();

mock.Setup(x => x.GetSalary(testId))

.Returns(salary);



mock.Setup(x => x.GetLengthOfWork(testId))

.Returns(length);





Act

var result = new Calculator(mock)

.Calculate13thSalary(testId);





Assert

Assert.AreEqual(expected, result, 0.01);

Arrange

var order = new Order(…) {…};

var mock = new Mock();







Act

new OrderProcessor(mock.Object).Process(order);









Assert

mock.Verify(x => x.Send(…, order.Customer));

Mock Frameworks

Moq

RhinoMocks

TypeMock.NET

Moq

The one I use.

Simple and convenient, but requires .NET 3.5.





mock.Setup(x => x.GetSalary(testId))

.Returns(salary);









http://moq.me/

RhinoMocks



Older than Moq, covers a lot of edge cases.

Complex API, but works on .NET 2.0.





Expect.Call(mock.GetSalary(testId))

.Return(salary);









http://www.ayende.com/projects/rhino-mocks.aspx

TypeMock.NET



Commercial mocking framework.



Virtual Mock concept:

Can mock concrete classes, static methods, etc.



May be useful with legacy code.







http://www.typemock.com/

Coverage

Coverage is a measure on

how much of your code is

tested.

Tools

NCover

Best coverage tool for .NET

Commercial, free version exist (but limited).





PartCover

Free, but less features than NCover

Coverage

Is a formal metric

Does not equal "well-tested"



However, coverage < 75% may

mean something is wrong

Bonus

Knowledge

Pex

Microsoft Research project.

Automatically generates tests for source code.





[PexTest]

public void TestCalculator(

double salary,

int stage,

double expected

)







http://research.microsoft.com/Pex/

Start now

Gallio: http://www.gallio.org/Downloads.aspx

Moq: http://moq.me/downloads/list

Questions


Share This Document



Related docs
Other docs by Andrey Shcheki...
Practical Unit-Testing in .NET
Views: 140  |  Downloads: 7
Introduction to C#
Views: 207  |  Downloads: 12
ASP.NET MVC
Views: 992  |  Downloads: 81
Enterprise development
Views: 658  |  Downloads: 7
Databases and Data Access in .NET
Views: 103  |  Downloads: 10
.NET Overview
Views: 389  |  Downloads: 9
by registering with docstoc.com you agree to our
privacy policy

You are almost ready to download!

You are almost ready to download!