Practical Unit-Testing in .NET

Reviews
Shared by: Andrey Shchekin
Stats
views:
78
rating:
not rated
reviews:
0
posted:
12/3/2009
language:
English
pages:
0
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 Performance Load Stress Tests 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] [Test] == [TestClass] == [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. 2. 3. 4. Row testing Type testing Parallel testing … 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 Repositories User Interface 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: Moq: http://www.gallio.org/Downloads.aspx http://moq.me/downloads/list Questions


Related docs
Practical .NET Unit Testing
Views: 2  |  Downloads: 1
JUnitNUnit-Unit testing frameworks
Views: 0  |  Downloads: 0
Distributed Unit Testing
Views: 0  |  Downloads: 0
Practical Unit Testing jUnit
Views: 0  |  Downloads: 0
Unit testing (OHJ-306x)
Views: 0  |  Downloads: 0
why bother to unit testing
Views: 27  |  Downloads: 2
Unit Testing 101
Views: 0  |  Downloads: 0
Code Generation forA xiom-based Unit Testing
Views: 1  |  Downloads: 0
Automated Unit Testing with JUnit
Views: 16  |  Downloads: 2
practical perl
Views: 8  |  Downloads: 1
Other docs by Andrey Shcheki...
Enterprise development
Views: 593  |  Downloads: 7
Databases and Data Access in .NET
Views: 78  |  Downloads: 9
ASP.NET MVC
Views: 832  |  Downloads: 71
Practical Unit-Testing in .NET
Views: 78  |  Downloads: 5
.NET Overview
Views: 345  |  Downloads: 9
Introduction to C#
Views: 164  |  Downloads: 11