SlideShare a Scribd company logo
The secret unit testing tools no one has
ever told you about
Dror Helper | blog.drorhelper.com | @dhelper
Join the conversation on Twitter: @DevWeek // #DW2016 // #DevWeek
Join the conversation on Twitter: @DevWeek // #DW2016 // #DevWeek
About.ME
Consultant @CodeValue
Developing software (professionally) since 2002
Mocking code since 2008
Clean coder & Test Driven Developer
OzCode (a.k.a โ€œMagical debuggingโ€) Evangelist
Blogger: http://blog.drorhelper.com
Join the conversation on Twitter: @DevWeek // #DW2016 // #DevWeek
But it was not always like that
1st Attempt Failed!
2nd Attempt Failed!!!
New job +
UT + Mentor
Success
Join the conversation on Twitter: @DevWeek // #DW2016 // #DevWeek
Why should I care about tools?
Join the conversation on Twitter: @DevWeek // #DW2016 // #DevWeek
Background: unit testing tools
Join the conversation on Twitter: @DevWeek // #DW2016 // #DevWeek
Well known unit testing tools
Build Failed!
Join the conversation on Twitter: @DevWeek // #DW2016 // #DevWeek
Server
Dev Machine
Source ControlBuild Server
Test Runner
Code
Coverage
Build Agent
Unit Testing
Framework
Isolation
Framework
?
Join the conversation on Twitter: @DevWeek // #DW2016 // #DevWeek
xUnit test framework
Test Suite
Fixture
Test Case
Test Case
Test Case
Test Case
Test Case
Fixture
Test Case
Test Case
Fixture
Test Case
Test Case
Test Case
public class BeforeAndAfter {
[SetUp]
public void Initialize() {
}
[TearDown]
public void Cleanup() {
}
[Test]
public void test1() {
}
[Test]
public void test2() {
}
}
Join the conversation on Twitter: @DevWeek // #DW2016 // #DevWeek
Mocking Frameworks
Unit test
Code under test
DependencyFake object(s)
Join the conversation on Twitter: @DevWeek // #DW2016 // #DevWeek
What Mocking framework can do for you?
โ€ข Create Fake objects
โ€ข Set behavior on fake objects
โ€ข Verify method was called
โ€ข And more...
Join the conversation on Twitter: @DevWeek // #DW2016 // #DevWeek
[Test]
public void Calculate_ReturnTwoValidNumbers_ServerCalled()
{
IDataAccess fakeDataAccess = A.Fake<IDataAccess>();
A.CallTo(() => fakeDataAccess.GetData(A<string>.Ignored))
.Returns(new Tuple<int, int>(2, 3));
var fakeCalculatorService = A.Fake<ICalculatorService>();
var cut = new DistrobutedCalculator(fakeDataAccess, fakeCalculatorService);
cut.Calculate();
A.CallTo(() => fakeCalculatorService.Add(2,3)).MustHaveHappened();
}
These tools do not help us write good
unit tests
In fact, sometimes
they prevent us from
writing good unit tests!
Join the conversation on Twitter: @DevWeek // #DW2016 // #DevWeek
Definition: unit tests
Automated piece of code that invokes
a unit of work in the system and then
checks a single assumption about the
behavior of that unit of work
[Roy Osherove, The Art Of Unit Testing]
Join the conversation on Twitter: @DevWeek // #DW2016 // #DevWeek
Unit test structure
[Test]
public void MyTest()
{
}
Join the conversation on Twitter: @DevWeek // #DW2016 // #DevWeek
No guidance ๏ƒ  Fragile tests ๏ƒ  Stop unit testing
Join the conversation on Twitter: @DevWeek // #DW2016 // #DevWeek
What about AAA?
[Test]
public async void GetUserFromUrl() {
var clientFake = A.Fake<IJsonClient>();
A.CallTo(() => clientFake.HttpGetUncompressedAsync(A<string>.Ignored))
.Returns(Task.FromResult(JsonResult));
var userRepository = new UserRepository(clientFake);
var user = await userRepository.GetUser(11361);
var expected = new User {
Id=11361, DisplayName = "Dror Helper", ImageUrl=DefaultAvatar, Reputation=13904
};
Assert.That(user, Is.EqualTo(expected));
}
Arrange
๏ƒŸ Act
๏ƒŸ Assert
Join the conversation on Twitter: @DevWeek // #DW2016 // #DevWeek
Problem solved? Hardly!
โ€ข Where to start?
โ€ข How to test existing code?
โ€ข What about test structure?
โ€ข Integration tests vs. unit tests
โ€ข What is a โ€œunit of workโ€?
Join the conversation on Twitter: @DevWeek // #DW2016 // #DevWeek
Test setup (Arrange)
Join the conversation on Twitter: @DevWeek // #DW2016 // #DevWeek
Arrange issues
[TestMethod]
public async Task LoadUser_ReputationStaysTheSame_ReputationTrendSame() {
var user1 = new User {ImageUrl = "http://dummy.jpg", Reputation = 10};
var user2 = new User {ImageUrl = "http://dummy.jpg", Reputation = 10};
var fakeUserRepository = new FakeUserRepository(new[] { user1, user2 });
var viewModel = await InvokeAsync(() => new UserDetailsViewModel(fakeUserRepository));
await viewModel.LoadUser();
await viewModel.LoadUser();
var result = await InvokeAsync(() => ((SolidColorBrush)viewModel.ReputationTrend).Color);
Assert.AreEqual(Colors.White, result);
}
Join the conversation on Twitter: @DevWeek // #DW2016 // #DevWeek
Solution: Setup/TearDown
private UserDetailsViewModel _viewModel;
[TestInitialize]
public async Task InitilizeUserViewModel() {
var user1 = new User { ImageUrl = "http://dummy.jpg", Reputation = 10 };
var user2 = new User { ImageUrl = "http://dummy.jpg", Reputation = 10 };
var fakeUserRepository = new FakeUserRepository(new[] { user1, user2 });
_viewModel = await InvokeAsync(() => new UserDetailsViewModel(fakeUserRepository));
}
[TestMethod]
public async Task LoadUser_ReputationStaysTheSame_ReputationTrendSame() {
await _viewModel.LoadUser();
await _viewModel.LoadUser();
var result = InvokeAsync(() => ((SolidColorBrush)_viewModel.ReputationTrend).Color);
Assert.AreEqual(Colors.White, result);
}
Join the conversation on Twitter: @DevWeek // #DW2016 // #DevWeek
Why you shouldnโ€™t use Setup in unit tests
private UserDetailsViewModel _viewModel;
[TestInitialize]
public async Task InitilizeUserViewModel() {
var user1 = new User { ImageUrl = "http://dummy.jpg", Reputation = 10 };
var user2 = new User { ImageUrl = "http://dummy.jpg", Reputation = 10 };
var fakeUserRepository = new FakeUserRepository(new[] { user1, user2 });
_viewModel = await InvokeAsync(() => new UserDetailsViewModel(fakeUserRepository));
}
[TestMethod]
public async Task LoadUser_ReputationStaysTheSame_ReputationTrendSame() {
await _viewModel.LoadUser();
await _viewModel.LoadUser();
var result = InvokeAsync(() => ((SolidColorBrush)_viewModel.ReputationTrend).Color);
Assert.AreEqual(Colors.White, result);
}
Join the conversation on Twitter: @DevWeek // #DW2016 // #DevWeek
Solution: Extract to methods
[TestMethod]
public async Task LoadUser_ReputationStaysTheSame_ReputationTrendSame() {
var user1 = CreateUser(reputation: 10);
var user2 = CreateUser(reputation: 10);
var fakeUserRepository = new FakeUserRepository(new[] { user1, user2 });
var viewModel = await InvokeAsync(() => new UserDetailsViewModel(fakeUserRepository));
await viewModel.LoadUser();
await viewModel.LoadUser();
var result = await InvokeAsync(() => ((SolidColorBrush)viewModel.ReputationTrend).Color);
Assert.AreEqual(Colors.White, result);
}
Join the conversation on Twitter: @DevWeek // #DW2016 // #DevWeek
Over extraction
[TestMethod]
public async Task LoadUser_ReputationStaysTheSame() {
var viewModel = InitializeSystem(10, 10);
await viewModel.LoadUser();
await viewModel.LoadUser();
CheckColor(Colors.White, viewModel);
}
Join the conversation on Twitter: @DevWeek // #DW2016 // #DevWeek
The problem with factories
private User CreateUser(int reputation) {
return new User {
ImageUrl = "http://dummy.jpg",
Reputation = reputation
};
}
private User CreateUser(int reputation, string imageUrl) {
return new User
{
ImageUrl = imageUrl,
Reputation = reputation
};
}
Join the conversation on Twitter: @DevWeek // #DW2016 // #DevWeek
Builder pattern
class UserBuilder
{
private int _id, _reputation;
private string _displayName, _imageUrl;
public UserBuilder() {
_id = 1;
_displayName = "dummy";
_imageUrl = "http://dummy.jpg";
}
User Build() {
return new User {
Id = _id, DisplayName = _displayName, ImageUrl = _imageUrl, Reputation = _reputation
};
}
}
Join the conversation on Twitter: @DevWeek // #DW2016 // #DevWeek
Builder pattern (cont.)
class UserBuilder
{
...
public UserBuilder WithName(string displayName) {
_displayName = displayName;
return this;
}
public UserBuilder WithReputation(int reputation) {
_reputation = reputation;
return this;
}
...
}
var user1 = new UserBuilder()
.WithReputation(10)
.Build();
Join the conversation on Twitter: @DevWeek // #DW2016 // #DevWeek
Tool: AutoMocking Containers
Test Container SUT
http://blog.ploeh.dk/2013/03/11/auto-mocking-container/
New()
Configure
CreateCreate SUT
Act
Join the conversation on Twitter: @DevWeek // #DW2016 // #DevWeek
Automocking with AutoFixture
[Fact]
public void YellIfTouchHotIron() {
var fixture = new Fixture().Customize(new AutoFakeItEasyCustomization());
Fake<IMouth> fakeMouth = fixture.Freeze<Fake<IMouth>>();
Fake<IHand> fakeHand = fixture.Freeze<Fake<IHand>>();
A.CallTo(() => fakeHand.FakedObject.TouchIron(A<Iron>._)).Throws<BurnException>();
var brain = fixture.Create<Brain>();
brain.TouchIron(new Iron {IsHot = true});
A.CallTo(() => fakeMouth.FakedObject.Yell()).MustHaveHappened();
}
Join the conversation on Twitter: @DevWeek // #DW2016 // #DevWeek
Automocking with Typemock Isolator
[TestMethod]
public void FakeAllDependencies_ChangeBehavior()
{
var real = Isolate.Fake.Dependencies<ClassUnderTest>();
var fake = Isolate.GetFake<Dependency>(real);
Isolate.WhenCalled(() => fake.Multiplier).WillReturn(2);
var result = real.Calculate(1, 2);
Assert.AreEqual(6, result);
}
Join the conversation on Twitter: @DevWeek // #DW2016 // #DevWeek
Problem: Complex inputs
โ€ข Big objects
โ€ข Deep objects
โ€ข Need for precision
โ€ข Lack of knowledge
Join the conversation on Twitter: @DevWeek // #DW2016 // #DevWeek
Solution: use trivial inputs
Sometimes missing the point
Not always enough for โ€œreal testโ€
Join the conversation on Twitter: @DevWeek // #DW2016 // #DevWeek
Solution: Serialization
Supported in most programming languages (XML, json).
โ€ข Need development ๏ƒ  testing delayed
โ€ข Production code change ๏ƒ  indefinitely delayed
Join the conversation on Twitter: @DevWeek // #DW2016 // #DevWeek
Tool: Export using OzCode
Join the conversation on Twitter: @DevWeek // #DW2016 // #DevWeek
Verification (Assert)
Join the conversation on Twitter: @DevWeek // #DW2016 // #DevWeek
Can you spot the problem?
[TestMethod]
public void PerformSomeActionReturns42()
{
var myClass = ...
bool initOk = myClass.Initialize();
var result = myClass.PerformSomeAction();
Assert.IsTrue(initOk);
Assert.AreEqual(42, result);
}
http://stackoverflow.com/q/26400537/11361
Join the conversation on Twitter: @DevWeek // #DW2016 // #DevWeek
Can you spot the problem?
[TestMethod]
public void TestPasswordComplexity()
{
var result = _UserManager.ChangePasswordAsync(_TestUser.Id, "Password123!", "1!").Result; //Changes the password.
Assert.IsFalse(result.Succeeded);
result = _UserManager.ChangePasswordAsync(_TestUser.Id, "Password123!", "123456789").Result; //Changes the password.
Assert.IsFalse(result.Succeeded);
result = _UserManager.ChangePasswordAsync(_TestUser.Id, "Password123!", "123456789!").Result; //Changes the password.
Assert.IsFalse(result.Succeeded);
result = _UserManager.ChangePasswordAsync(_TestUser.Id, "Password123!", "abcdefghijk").Result; //Changes the password.
Assert.IsFalse(result.Succeeded);
result = _UserManager.ChangePasswordAsync(_TestUser.Id, "Password123!", "abcdefghijK1!").Result; //Changes the password.
Assert.IsTrue(result.Succeeded);
}
http://stackoverflow.com/q/26400537/11361
Join the conversation on Twitter: @DevWeek // #DW2016 // #DevWeek
How many Assert(s) per test?
One Assert Per Test!
Two Assert == Two Tests ๏ƒ  Usually ???
โ€(โ€ฆthe Code is more)
what you'd call guidelines
than actual rulesโ€
Join the conversation on Twitter: @DevWeek // #DW2016 // #DevWeek
Sometimes multiple asserts make sense
[TestMethod]
public void CompareTwoAsserts()
{
var actual = GetNextMessage();
Assert.AreEqual(1, actual.Id);
Assert.AreEqual("str-1", actual.Content);
}
Join the conversation on Twitter: @DevWeek // #DW2016 // #DevWeek
public class AssertAll
{
public static void Execute(params Action[] assertionsToRun)
{
var errorMessages = new List<exception>();
foreach (var action in assertionsToRun)
{
try
{
action.Invoke();
}
catch (Exception exc)
{
errorMessages.Add(exc);
}
}
if(errorMessages.Any())
{
var separator = string.Format("{0}{0}", Environment.NewLine);
string errorMessage = string.Join(separator, errorMessages);
Assert.Fail(string.Format("The following conditions failed:{0}{1}", Environment.NewLine, errorMessage));
}
}
}
http://blog.drorhelper.com/2011/02/multiple-asserts-done-right.html
Join the conversation on Twitter: @DevWeek // #DW2016 // #DevWeek
Using AssertAll
[TestMethod]
public void CompareTwoAsserts()
{
var actual = CreateMessage();
AssertAll.Execute(
() => Assert.AreEqual(1, actual.Id),
() => Assert.AreEqual("str-1", actual.Content);
}
Join the conversation on Twitter: @DevWeek // #DW2016 // #DevWeek
Some frameworks are catching up!
https://github.com/nunit/docs/wiki/Multiple-Asserts-Spec
Join the conversation on Twitter: @DevWeek // #DW2016 // #DevWeek
Ever had issues choosing the right Assert?
โ€ข IsTrue vs. AreEqual
โ€ข Parameter ordering confusion
โ€ข StringAssert/CollectionAssert
Itโ€™s all about proper error messages
Join the conversation on Twitter: @DevWeek // #DW2016 // #DevWeek
Tool: 3rd party assertion libraries
๏ƒผBetter error messages
๏ƒผReadability
๏ƒผMultiple asserts*
ร—Additional dependency
ร—Limited UT framework support
ร—System.Object โ€œSPAMEDโ€ by extension messages
Join the conversation on Twitter: @DevWeek // #DW2016 // #DevWeek
Shouldly
[Fact]
public void AddTest()
{
var calculator = new Calculator();
var result = calculator.Add(2, 3);
Assert.Equal(6, result);
}
[Fact]
public void AddTest_Shouldly()
{
var calculator = new Calculator();
var result = calculator.Add(2, 3);
result.ShouldBe(6);
}
https://github.com/shouldly/shouldly
Shouldly.ShouldAssertException
result
should be
6
but was
5
Xunit.Sdk.EqualException
Assert.Equal() Failure
Expected: 6
Actual: 5
Join the conversation on Twitter: @DevWeek // #DW2016 // #DevWeek
Shouldly
[Fact]
public void GetDivisorsTest()
{
var calculator = new Calculator();
var result = calculator.GetDivisors(20);
Assert.Equal(new[] {2,3,5,7}, result);
}
[Fact]
public void GetDivisorsTest_Shouldly()
{
var calculator = new Calculator();
var result = calculator.GetDivisors(20);
result.ShouldBe(new[] { 2, 3, 5, 7 });
}
https://github.com/shouldly/shouldly
Shouldly.ShouldAssertException
result
should be
[2, 3, 5, 7]
but was
[2, 4, 5, 10]
difference
[2, *4*, 5, *10*]
Xunit.Sdk.EqualException
Assert.Equal() Failure
Expected: Int32[] [2, 3, 5, 7]
Actual: WhereEnumerableIterator<Int32> [2, 4, 5, 10]
Join the conversation on Twitter: @DevWeek // #DW2016 // #DevWeek
FluentAssertions
[Fact]
public void CompareTwoObjects()
{
var customer1 = new Customer("cust-1", "John Doe");
var customer2 = new Customer("cust-2", "John Doe");
customer1.ShouldBeEquivalentTo(customer2,
o => o.Excluding(customer => customer.Id));
}
http://www.fluentassertions.com/
Join the conversation on Twitter: @DevWeek // #DW2016 // #DevWeek
AssertHelper
[Test]
public void CheckCompare()
{
var myClass = new MyClass();
Expect.That(() => myClass.ReturnFive() == 10);
}
[Test]
public void CheckTrue()
{
var myClass = new MyClass();
Expect.That(() => myClass.ReturnFalse() == true);
}
[Test]
public void StringStartsWith() {
var s1 = "1234567890";
Expect.That(() => s1.StartsWith("456"));
}
[Test]
public void CollectionContains()
{
var c1 = new[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 0 };
Expect.That(() => c1.Contains(41));
}
https://github.com/dhelper/AssertHelper
Join the conversation on Twitter: @DevWeek // #DW2016 // #DevWeek
Test organization
Join the conversation on Twitter: @DevWeek // #DW2016 // #DevWeek
Test structure issues
โ€ข What to call the test?
โ€ข AAA is not mandatory
โ€ข What should I test?
โ€ข How to avoid unreadable, complicated tests?
- Unit testing framework provide no structure
Join the conversation on Twitter: @DevWeek // #DW2016 // #DevWeek
The BDD approach
Step
Definitions
Join the conversation on Twitter: @DevWeek // #DW2016 // #DevWeek
Specifications == focused test
Feature: Addition
In order to avoid silly mistakes
As a math idiot
I want to be told the sum of two numbers
Scenario: Add two numbers
Given I have entered 50 into the calculator
And I have entered 70 into the calculator
When I press add
Then the result should be 120 on the screen
Join the conversation on Twitter: @DevWeek // #DW2016 // #DevWeek
BDD Example: SpecFlow
http://www.specflow.org/
Join the conversation on Twitter: @DevWeek // #DW2016 // #DevWeek
Tool: BDDfy
[TestClass]
public class CardHasBeenDisabled {
private Card _card;
private Atm _subject;
void GivenTheCardIsDisabled() {
_card = new Card(false, 100);
_subject = new Atm(100);
}
void WhenTheAccountHolderRequestsMoney() {
_subject.RequestMoney(_card, 20);
}
void ThenTheAtmShouldRetainTheCard() {
Assert.IsTrue(_subject.CardIsRetained);
}
void AndTheAtmShouldSayTheCardHasBeenRetained() {
Assert.AreEqual(DisplayMessage.CardIsRetained, _subject.Message);
}
[TestMethod]
public void Execute()
{
this.BDDfy();
}
}
Join the conversation on Twitter: @DevWeek // #DW2016 // #DevWeek
Test execution
Join the conversation on Twitter: @DevWeek // #DW2016 // #DevWeek
Everybody needs a CI server
Unit tests without a CI server are a waste of time
- if you're running all of the tests all of the time
locally you're a better man then I am
Join the conversation on Twitter: @DevWeek // #DW2016 // #DevWeek
Tool: Continuous testing
DotCover
Typemock Runner
nCrunch
Join the conversation on Twitter: @DevWeek // #DW2016 // #DevWeek
The right tools will help you write good tests
Arrange
Builder Pattern
AutoMocking
Containers
Export
Assert
Shouldly
FluentAssertions
AssertHelper
Test
Structure
BDDfy
Continuous
Testing
Typemock
Runner
DotCover
nCrunch
Join the conversation on Twitter: @DevWeek // #DW2016 // #DevWeek
Thank you
Dror Helper | @dhelper | http://blog.drorhelper.com

More Related Content

What's hot (20)

PDF
Implementing Quality on a Java Project
Vincent Massol
ย 
PDF
Kiss PageObjects [01-2017]
Iakiv Kramarenko
ย 
PDF
How to setup unit testing in Android Studio
tobiaspreuss
ย 
PDF
Plugin for Plugin, ะธะปะธ ั€ะฐััˆะธั€ัะตะผ Android New Build System. ะะฝั‚ะพะฝ ะ ัƒั‚ะบะตะฒะธั‡
Yandex
ย 
PDF
Polyglot automation - QA Fest - 2015
Iakiv Kramarenko
ย 
PPT
Swtbot
cristitep
ย 
PPTX
XCUITest for iOS App Testing and how to test with Xcode
pCloudy
ย 
PDF
Automated Xcode 7 UI Testing
Jouni Miettunen
ย 
PDF
React.js: You deserve to know about it
Anderson Aguiar
ย 
PDF
Abstraction Layers Test Management Summit Faciliated Session 2014
Alan Richardson
ย 
PPT
JsUnit
Alex Chaffee
ย 
PDF
Learn How to Unit Test Your Android Application (with Robolectric)
Marakana Inc.
ย 
PPTX
SwtBot: Unit Testing Made Easy
Ankit Goel
ย 
PDF
Advanced Dagger talk from 360andev
Mike Nakhimovich
ย 
PDF
Functional Testing made easy with SWTBot for Developers and Testers
Aurรฉlien Pupier
ย 
PDF
Unit testing and Android
Tomรกลก Kypta
ย 
PPTX
Robolectric Adventure
Eugen Martynov
ย 
PPTX
Eyes or heart
Yevhen Rudiev
ย 
PDF
Iasi code camp 20 april 2013 implement-quality-java-massol-codecamp
Codecamp Romania
ย 
PDF
More android code puzzles
Danny Preussler
ย 
Implementing Quality on a Java Project
Vincent Massol
ย 
Kiss PageObjects [01-2017]
Iakiv Kramarenko
ย 
How to setup unit testing in Android Studio
tobiaspreuss
ย 
Plugin for Plugin, ะธะปะธ ั€ะฐััˆะธั€ัะตะผ Android New Build System. ะะฝั‚ะพะฝ ะ ัƒั‚ะบะตะฒะธั‡
Yandex
ย 
Polyglot automation - QA Fest - 2015
Iakiv Kramarenko
ย 
Swtbot
cristitep
ย 
XCUITest for iOS App Testing and how to test with Xcode
pCloudy
ย 
Automated Xcode 7 UI Testing
Jouni Miettunen
ย 
React.js: You deserve to know about it
Anderson Aguiar
ย 
Abstraction Layers Test Management Summit Faciliated Session 2014
Alan Richardson
ย 
JsUnit
Alex Chaffee
ย 
Learn How to Unit Test Your Android Application (with Robolectric)
Marakana Inc.
ย 
SwtBot: Unit Testing Made Easy
Ankit Goel
ย 
Advanced Dagger talk from 360andev
Mike Nakhimovich
ย 
Functional Testing made easy with SWTBot for Developers and Testers
Aurรฉlien Pupier
ย 
Unit testing and Android
Tomรกลก Kypta
ย 
Robolectric Adventure
Eugen Martynov
ย 
Eyes or heart
Yevhen Rudiev
ย 
Iasi code camp 20 april 2013 implement-quality-java-massol-codecamp
Codecamp Romania
ย 
More android code puzzles
Danny Preussler
ย 

Viewers also liked (9)

PPTX
Presentation ch 6
Nashonna Haynes
ย 
PPTX
Electronics 101 for software developers
Dror Helper
ย 
PPT
ะฐะทะธะทะฐ ะพะผะฐั€ะพะฒะฐ ั„ะธั‚ะฝะตั ะบะปัƒะฑ ะฟั€ะตะดะฟั€ะธะฝะธะผะฐั‚ะตะปัŒ
Aziza Omarova
ย 
PPS
SEGUNDA GUERRA MUNDIAL
Manu Villajos Ortega
ย 
PPTX
El blog de box
Jorge Cesar Mendoza Guerra
ย 
PPTX
Finding PR Success on Reddit
Donny Schell
ย 
PPTX
INDUSTRIAL TRAINING(PPT) DLW,Varanasi
ak3793
ย 
PPTX
PRESENTATION ON DIESEL TRACTION CENTRE GONDA
ABDUS SAMAD
ย 
PPTX
Loco diesel shed, pulera
ashjm
ย 
Presentation ch 6
Nashonna Haynes
ย 
Electronics 101 for software developers
Dror Helper
ย 
ะฐะทะธะทะฐ ะพะผะฐั€ะพะฒะฐ ั„ะธั‚ะฝะตั ะบะปัƒะฑ ะฟั€ะตะดะฟั€ะธะฝะธะผะฐั‚ะตะปัŒ
Aziza Omarova
ย 
SEGUNDA GUERRA MUNDIAL
Manu Villajos Ortega
ย 
El blog de box
Jorge Cesar Mendoza Guerra
ย 
Finding PR Success on Reddit
Donny Schell
ย 
INDUSTRIAL TRAINING(PPT) DLW,Varanasi
ak3793
ย 
PRESENTATION ON DIESEL TRACTION CENTRE GONDA
ABDUS SAMAD
ย 
Loco diesel shed, pulera
ashjm
ย 
Ad

Similar to Secret unit testing tools (20)

PPTX
Secret unit testing tools no one ever told you about
Dror Helper
ย 
PDF
Djangocon 2014 angular + django
Nina Zakharenko
ย 
PPTX
Unit testing on mobile apps
BuลŸra Deniz, CSM
ย 
PPTX
The secret unit testing tools no one has ever told you about
Dror Helper
ย 
PPTX
Breaking Dependencies to Allow Unit Testing
Steven Smith
ย 
PDF
Get Hip with JHipster - GIDS 2019
Matt Raible
ย 
PDF
Refactor your way forward
Jorge Ortiz
ย 
PDF
Test-driven Development with Drupal and Codeception (DrupalCamp Brighton)
Cogapp
ย 
PPTX
Tdd is not about testing (OOP)
Gianluca Padovani
ย 
PPTX
Async task, threads, pools, and executors oh my!
Stacy Devino
ย 
PPTX
Xam expertday
Codrina Merigo
ย 
PPT
Testing And Drupal
Peter Arato
ย 
PPTX
Testing with VS2010 - A Bugs Life
Peter Gfader
ย 
PDF
Art of unit testing: how to do it right
Dmytro Patserkovskyi
ย 
PPTX
The secret unit testing tools no one ever told you about
Dror Helper
ย 
PDF
Developing your own OpenStack Swift middleware
Christian Schwede
ย 
PPTX
Testing ASP.NET - Progressive.NET
Ben Hall
ย 
PDF
Reactive Type safe Webcomponents with skateJS
Martin Hochel
ย 
PDF
Developer Tests - Things to Know
Vaidas Pilkauskas
ย 
PPTX
The real beginner's guide to android testing
Eric (Trung Dung) Nguyen
ย 
Secret unit testing tools no one ever told you about
Dror Helper
ย 
Djangocon 2014 angular + django
Nina Zakharenko
ย 
Unit testing on mobile apps
BuลŸra Deniz, CSM
ย 
The secret unit testing tools no one has ever told you about
Dror Helper
ย 
Breaking Dependencies to Allow Unit Testing
Steven Smith
ย 
Get Hip with JHipster - GIDS 2019
Matt Raible
ย 
Refactor your way forward
Jorge Ortiz
ย 
Test-driven Development with Drupal and Codeception (DrupalCamp Brighton)
Cogapp
ย 
Tdd is not about testing (OOP)
Gianluca Padovani
ย 
Async task, threads, pools, and executors oh my!
Stacy Devino
ย 
Xam expertday
Codrina Merigo
ย 
Testing And Drupal
Peter Arato
ย 
Testing with VS2010 - A Bugs Life
Peter Gfader
ย 
Art of unit testing: how to do it right
Dmytro Patserkovskyi
ย 
The secret unit testing tools no one ever told you about
Dror Helper
ย 
Developing your own OpenStack Swift middleware
Christian Schwede
ย 
Testing ASP.NET - Progressive.NET
Ben Hall
ย 
Reactive Type safe Webcomponents with skateJS
Martin Hochel
ย 
Developer Tests - Things to Know
Vaidas Pilkauskas
ย 
The real beginner's guide to android testing
Eric (Trung Dung) Nguyen
ย 
Ad

More from Dror Helper (20)

PPTX
Unit testing patterns for concurrent code
Dror Helper
ย 
PPTX
Debugging with visual studio beyond 'F5'
Dror Helper
ย 
PPTX
From clever code to better code
Dror Helper
ย 
PPTX
From clever code to better code
Dror Helper
ย 
PPTX
A software developer guide to working with aws
Dror Helper
ย 
PPTX
The role of the architect in agile
Dror Helper
ย 
PDF
Harnessing the power of aws using dot net core
Dror Helper
ย 
PPTX
Developing multi-platform microservices using .NET core
Dror Helper
ย 
PPTX
Harnessing the power of aws using dot net
Dror Helper
ย 
PPTX
C++ Unit testing - the good, the bad & the ugly
Dror Helper
ย 
PPTX
Working with c++ legacy code
Dror Helper
ย 
PPTX
Visual Studio tricks every dot net developer should know
Dror Helper
ย 
PPTX
Navigating the xDD Alphabet Soup
Dror Helper
ย 
PPTX
Building unit tests correctly
Dror Helper
ย 
PPTX
Whoโ€™s afraid of WinDbg
Dror Helper
ย 
PPTX
Unit testing patterns for concurrent code
Dror Helper
ย 
PPTX
Designing with tests
Dror Helper
ย 
PPTX
Building unit tests correctly with visual studio 2013
Dror Helper
ย 
PPTX
Writing clean code in C# and .NET
Dror Helper
ย 
PPTX
Using FakeIteasy
Dror Helper
ย 
Unit testing patterns for concurrent code
Dror Helper
ย 
Debugging with visual studio beyond 'F5'
Dror Helper
ย 
From clever code to better code
Dror Helper
ย 
From clever code to better code
Dror Helper
ย 
A software developer guide to working with aws
Dror Helper
ย 
The role of the architect in agile
Dror Helper
ย 
Harnessing the power of aws using dot net core
Dror Helper
ย 
Developing multi-platform microservices using .NET core
Dror Helper
ย 
Harnessing the power of aws using dot net
Dror Helper
ย 
C++ Unit testing - the good, the bad & the ugly
Dror Helper
ย 
Working with c++ legacy code
Dror Helper
ย 
Visual Studio tricks every dot net developer should know
Dror Helper
ย 
Navigating the xDD Alphabet Soup
Dror Helper
ย 
Building unit tests correctly
Dror Helper
ย 
Whoโ€™s afraid of WinDbg
Dror Helper
ย 
Unit testing patterns for concurrent code
Dror Helper
ย 
Designing with tests
Dror Helper
ย 
Building unit tests correctly with visual studio 2013
Dror Helper
ย 
Writing clean code in C# and .NET
Dror Helper
ย 
Using FakeIteasy
Dror Helper
ย 

Recently uploaded (20)

PDF
Step-by-Step Guide to Install SAP HANA Studio | Complete Installation Tutoria...
SAP Vista, an A L T Z E N Company
ย 
PDF
Meet in the Middle: Solving the Low-Latency Challenge for Agentic AI
Alluxio, Inc.
ย 
PDF
Instantiations Company Update (ESUG 2025)
ESUG
ย 
PDF
chapter 5.pdf cyber security and Internet of things
PalakSharma980227
ย 
PPTX
Chess King 25.0.0.2500 With Crack Full Free Download
cracked shares
ย 
PDF
ESUG 2025: Pharo 13 and Beyond (Stephane Ducasse)
ESUG
ย 
PDF
Show Which Projects Support Your Strategy and Deliver Results with OnePlan df
OnePlan Solutions
ย 
PPTX
API DOCUMENTATION | API INTEGRATION PLATFORM
philipnathen82
ย 
PPTX
Transforming Insights: How Generative AI is Revolutionizing Data Analytics
LetsAI Solutions
ย 
PDF
Australian Enterprises Need Project Service Automation
Navision India
ย 
PPTX
prodad heroglyph crack 2.0.214.2 Full Free Download
cracked shares
ย 
PDF
How Attendance Management Software is Revolutionizing Education.pdf
Pikmykid
ย 
PDF
Message Level Status (MLS): The Instant Feedback Mechanism for UAE e-Invoicin...
Prachi Desai
ย 
PDF
Introduction to Apache Icebergโ„ข & Tableflow
Alluxio, Inc.
ย 
PPTX
Smart Doctor Appointment Booking option in odoo.pptx
AxisTechnolabs
ย 
PPTX
Cutting Optimization Pro 5.18.2 Crack With Free Download
cracked shares
ย 
PDF
Optimizing Tiered Storage for Low-Latency Real-Time Analytics at AI Scale
Alluxio, Inc.
ย 
PDF
Odoo Customization Services by CandidRoot Solutions
CandidRoot Solutions Private Limited
ย 
PPTX
SAP Public Cloud PPT , SAP PPT, Public Cloud PPT
sonawanekundan2024
ย 
PDF
Code and No-Code Journeys: The Maintenance Shortcut
Applitools
ย 
Step-by-Step Guide to Install SAP HANA Studio | Complete Installation Tutoria...
SAP Vista, an A L T Z E N Company
ย 
Meet in the Middle: Solving the Low-Latency Challenge for Agentic AI
Alluxio, Inc.
ย 
Instantiations Company Update (ESUG 2025)
ESUG
ย 
chapter 5.pdf cyber security and Internet of things
PalakSharma980227
ย 
Chess King 25.0.0.2500 With Crack Full Free Download
cracked shares
ย 
ESUG 2025: Pharo 13 and Beyond (Stephane Ducasse)
ESUG
ย 
Show Which Projects Support Your Strategy and Deliver Results with OnePlan df
OnePlan Solutions
ย 
API DOCUMENTATION | API INTEGRATION PLATFORM
philipnathen82
ย 
Transforming Insights: How Generative AI is Revolutionizing Data Analytics
LetsAI Solutions
ย 
Australian Enterprises Need Project Service Automation
Navision India
ย 
prodad heroglyph crack 2.0.214.2 Full Free Download
cracked shares
ย 
How Attendance Management Software is Revolutionizing Education.pdf
Pikmykid
ย 
Message Level Status (MLS): The Instant Feedback Mechanism for UAE e-Invoicin...
Prachi Desai
ย 
Introduction to Apache Icebergโ„ข & Tableflow
Alluxio, Inc.
ย 
Smart Doctor Appointment Booking option in odoo.pptx
AxisTechnolabs
ย 
Cutting Optimization Pro 5.18.2 Crack With Free Download
cracked shares
ย 
Optimizing Tiered Storage for Low-Latency Real-Time Analytics at AI Scale
Alluxio, Inc.
ย 
Odoo Customization Services by CandidRoot Solutions
CandidRoot Solutions Private Limited
ย 
SAP Public Cloud PPT , SAP PPT, Public Cloud PPT
sonawanekundan2024
ย 
Code and No-Code Journeys: The Maintenance Shortcut
Applitools
ย 

Secret unit testing tools

  • 1. The secret unit testing tools no one has ever told you about Dror Helper | blog.drorhelper.com | @dhelper Join the conversation on Twitter: @DevWeek // #DW2016 // #DevWeek
  • 2. Join the conversation on Twitter: @DevWeek // #DW2016 // #DevWeek About.ME Consultant @CodeValue Developing software (professionally) since 2002 Mocking code since 2008 Clean coder & Test Driven Developer OzCode (a.k.a โ€œMagical debuggingโ€) Evangelist Blogger: http://blog.drorhelper.com
  • 3. Join the conversation on Twitter: @DevWeek // #DW2016 // #DevWeek But it was not always like that 1st Attempt Failed! 2nd Attempt Failed!!! New job + UT + Mentor Success
  • 4. Join the conversation on Twitter: @DevWeek // #DW2016 // #DevWeek Why should I care about tools?
  • 5. Join the conversation on Twitter: @DevWeek // #DW2016 // #DevWeek Background: unit testing tools
  • 6. Join the conversation on Twitter: @DevWeek // #DW2016 // #DevWeek Well known unit testing tools Build Failed!
  • 7. Join the conversation on Twitter: @DevWeek // #DW2016 // #DevWeek Server Dev Machine Source ControlBuild Server Test Runner Code Coverage Build Agent Unit Testing Framework Isolation Framework ?
  • 8. Join the conversation on Twitter: @DevWeek // #DW2016 // #DevWeek xUnit test framework Test Suite Fixture Test Case Test Case Test Case Test Case Test Case Fixture Test Case Test Case Fixture Test Case Test Case Test Case public class BeforeAndAfter { [SetUp] public void Initialize() { } [TearDown] public void Cleanup() { } [Test] public void test1() { } [Test] public void test2() { } }
  • 9. Join the conversation on Twitter: @DevWeek // #DW2016 // #DevWeek Mocking Frameworks Unit test Code under test DependencyFake object(s)
  • 10. Join the conversation on Twitter: @DevWeek // #DW2016 // #DevWeek What Mocking framework can do for you? โ€ข Create Fake objects โ€ข Set behavior on fake objects โ€ข Verify method was called โ€ข And more...
  • 11. Join the conversation on Twitter: @DevWeek // #DW2016 // #DevWeek [Test] public void Calculate_ReturnTwoValidNumbers_ServerCalled() { IDataAccess fakeDataAccess = A.Fake<IDataAccess>(); A.CallTo(() => fakeDataAccess.GetData(A<string>.Ignored)) .Returns(new Tuple<int, int>(2, 3)); var fakeCalculatorService = A.Fake<ICalculatorService>(); var cut = new DistrobutedCalculator(fakeDataAccess, fakeCalculatorService); cut.Calculate(); A.CallTo(() => fakeCalculatorService.Add(2,3)).MustHaveHappened(); }
  • 12. These tools do not help us write good unit tests In fact, sometimes they prevent us from writing good unit tests!
  • 13. Join the conversation on Twitter: @DevWeek // #DW2016 // #DevWeek Definition: unit tests Automated piece of code that invokes a unit of work in the system and then checks a single assumption about the behavior of that unit of work [Roy Osherove, The Art Of Unit Testing]
  • 14. Join the conversation on Twitter: @DevWeek // #DW2016 // #DevWeek Unit test structure [Test] public void MyTest() { }
  • 15. Join the conversation on Twitter: @DevWeek // #DW2016 // #DevWeek No guidance ๏ƒ  Fragile tests ๏ƒ  Stop unit testing
  • 16. Join the conversation on Twitter: @DevWeek // #DW2016 // #DevWeek What about AAA? [Test] public async void GetUserFromUrl() { var clientFake = A.Fake<IJsonClient>(); A.CallTo(() => clientFake.HttpGetUncompressedAsync(A<string>.Ignored)) .Returns(Task.FromResult(JsonResult)); var userRepository = new UserRepository(clientFake); var user = await userRepository.GetUser(11361); var expected = new User { Id=11361, DisplayName = "Dror Helper", ImageUrl=DefaultAvatar, Reputation=13904 }; Assert.That(user, Is.EqualTo(expected)); } Arrange ๏ƒŸ Act ๏ƒŸ Assert
  • 17. Join the conversation on Twitter: @DevWeek // #DW2016 // #DevWeek Problem solved? Hardly! โ€ข Where to start? โ€ข How to test existing code? โ€ข What about test structure? โ€ข Integration tests vs. unit tests โ€ข What is a โ€œunit of workโ€?
  • 18. Join the conversation on Twitter: @DevWeek // #DW2016 // #DevWeek Test setup (Arrange)
  • 19. Join the conversation on Twitter: @DevWeek // #DW2016 // #DevWeek Arrange issues [TestMethod] public async Task LoadUser_ReputationStaysTheSame_ReputationTrendSame() { var user1 = new User {ImageUrl = "http://dummy.jpg", Reputation = 10}; var user2 = new User {ImageUrl = "http://dummy.jpg", Reputation = 10}; var fakeUserRepository = new FakeUserRepository(new[] { user1, user2 }); var viewModel = await InvokeAsync(() => new UserDetailsViewModel(fakeUserRepository)); await viewModel.LoadUser(); await viewModel.LoadUser(); var result = await InvokeAsync(() => ((SolidColorBrush)viewModel.ReputationTrend).Color); Assert.AreEqual(Colors.White, result); }
  • 20. Join the conversation on Twitter: @DevWeek // #DW2016 // #DevWeek Solution: Setup/TearDown private UserDetailsViewModel _viewModel; [TestInitialize] public async Task InitilizeUserViewModel() { var user1 = new User { ImageUrl = "http://dummy.jpg", Reputation = 10 }; var user2 = new User { ImageUrl = "http://dummy.jpg", Reputation = 10 }; var fakeUserRepository = new FakeUserRepository(new[] { user1, user2 }); _viewModel = await InvokeAsync(() => new UserDetailsViewModel(fakeUserRepository)); } [TestMethod] public async Task LoadUser_ReputationStaysTheSame_ReputationTrendSame() { await _viewModel.LoadUser(); await _viewModel.LoadUser(); var result = InvokeAsync(() => ((SolidColorBrush)_viewModel.ReputationTrend).Color); Assert.AreEqual(Colors.White, result); }
  • 21. Join the conversation on Twitter: @DevWeek // #DW2016 // #DevWeek Why you shouldnโ€™t use Setup in unit tests private UserDetailsViewModel _viewModel; [TestInitialize] public async Task InitilizeUserViewModel() { var user1 = new User { ImageUrl = "http://dummy.jpg", Reputation = 10 }; var user2 = new User { ImageUrl = "http://dummy.jpg", Reputation = 10 }; var fakeUserRepository = new FakeUserRepository(new[] { user1, user2 }); _viewModel = await InvokeAsync(() => new UserDetailsViewModel(fakeUserRepository)); } [TestMethod] public async Task LoadUser_ReputationStaysTheSame_ReputationTrendSame() { await _viewModel.LoadUser(); await _viewModel.LoadUser(); var result = InvokeAsync(() => ((SolidColorBrush)_viewModel.ReputationTrend).Color); Assert.AreEqual(Colors.White, result); }
  • 22. Join the conversation on Twitter: @DevWeek // #DW2016 // #DevWeek Solution: Extract to methods [TestMethod] public async Task LoadUser_ReputationStaysTheSame_ReputationTrendSame() { var user1 = CreateUser(reputation: 10); var user2 = CreateUser(reputation: 10); var fakeUserRepository = new FakeUserRepository(new[] { user1, user2 }); var viewModel = await InvokeAsync(() => new UserDetailsViewModel(fakeUserRepository)); await viewModel.LoadUser(); await viewModel.LoadUser(); var result = await InvokeAsync(() => ((SolidColorBrush)viewModel.ReputationTrend).Color); Assert.AreEqual(Colors.White, result); }
  • 23. Join the conversation on Twitter: @DevWeek // #DW2016 // #DevWeek Over extraction [TestMethod] public async Task LoadUser_ReputationStaysTheSame() { var viewModel = InitializeSystem(10, 10); await viewModel.LoadUser(); await viewModel.LoadUser(); CheckColor(Colors.White, viewModel); }
  • 24. Join the conversation on Twitter: @DevWeek // #DW2016 // #DevWeek The problem with factories private User CreateUser(int reputation) { return new User { ImageUrl = "http://dummy.jpg", Reputation = reputation }; } private User CreateUser(int reputation, string imageUrl) { return new User { ImageUrl = imageUrl, Reputation = reputation }; }
  • 25. Join the conversation on Twitter: @DevWeek // #DW2016 // #DevWeek Builder pattern class UserBuilder { private int _id, _reputation; private string _displayName, _imageUrl; public UserBuilder() { _id = 1; _displayName = "dummy"; _imageUrl = "http://dummy.jpg"; } User Build() { return new User { Id = _id, DisplayName = _displayName, ImageUrl = _imageUrl, Reputation = _reputation }; } }
  • 26. Join the conversation on Twitter: @DevWeek // #DW2016 // #DevWeek Builder pattern (cont.) class UserBuilder { ... public UserBuilder WithName(string displayName) { _displayName = displayName; return this; } public UserBuilder WithReputation(int reputation) { _reputation = reputation; return this; } ... } var user1 = new UserBuilder() .WithReputation(10) .Build();
  • 27. Join the conversation on Twitter: @DevWeek // #DW2016 // #DevWeek Tool: AutoMocking Containers Test Container SUT http://blog.ploeh.dk/2013/03/11/auto-mocking-container/ New() Configure CreateCreate SUT Act
  • 28. Join the conversation on Twitter: @DevWeek // #DW2016 // #DevWeek Automocking with AutoFixture [Fact] public void YellIfTouchHotIron() { var fixture = new Fixture().Customize(new AutoFakeItEasyCustomization()); Fake<IMouth> fakeMouth = fixture.Freeze<Fake<IMouth>>(); Fake<IHand> fakeHand = fixture.Freeze<Fake<IHand>>(); A.CallTo(() => fakeHand.FakedObject.TouchIron(A<Iron>._)).Throws<BurnException>(); var brain = fixture.Create<Brain>(); brain.TouchIron(new Iron {IsHot = true}); A.CallTo(() => fakeMouth.FakedObject.Yell()).MustHaveHappened(); }
  • 29. Join the conversation on Twitter: @DevWeek // #DW2016 // #DevWeek Automocking with Typemock Isolator [TestMethod] public void FakeAllDependencies_ChangeBehavior() { var real = Isolate.Fake.Dependencies<ClassUnderTest>(); var fake = Isolate.GetFake<Dependency>(real); Isolate.WhenCalled(() => fake.Multiplier).WillReturn(2); var result = real.Calculate(1, 2); Assert.AreEqual(6, result); }
  • 30. Join the conversation on Twitter: @DevWeek // #DW2016 // #DevWeek Problem: Complex inputs โ€ข Big objects โ€ข Deep objects โ€ข Need for precision โ€ข Lack of knowledge
  • 31. Join the conversation on Twitter: @DevWeek // #DW2016 // #DevWeek Solution: use trivial inputs Sometimes missing the point Not always enough for โ€œreal testโ€
  • 32. Join the conversation on Twitter: @DevWeek // #DW2016 // #DevWeek Solution: Serialization Supported in most programming languages (XML, json). โ€ข Need development ๏ƒ  testing delayed โ€ข Production code change ๏ƒ  indefinitely delayed
  • 33. Join the conversation on Twitter: @DevWeek // #DW2016 // #DevWeek Tool: Export using OzCode
  • 34. Join the conversation on Twitter: @DevWeek // #DW2016 // #DevWeek Verification (Assert)
  • 35. Join the conversation on Twitter: @DevWeek // #DW2016 // #DevWeek Can you spot the problem? [TestMethod] public void PerformSomeActionReturns42() { var myClass = ... bool initOk = myClass.Initialize(); var result = myClass.PerformSomeAction(); Assert.IsTrue(initOk); Assert.AreEqual(42, result); } http://stackoverflow.com/q/26400537/11361
  • 36. Join the conversation on Twitter: @DevWeek // #DW2016 // #DevWeek Can you spot the problem? [TestMethod] public void TestPasswordComplexity() { var result = _UserManager.ChangePasswordAsync(_TestUser.Id, "Password123!", "1!").Result; //Changes the password. Assert.IsFalse(result.Succeeded); result = _UserManager.ChangePasswordAsync(_TestUser.Id, "Password123!", "123456789").Result; //Changes the password. Assert.IsFalse(result.Succeeded); result = _UserManager.ChangePasswordAsync(_TestUser.Id, "Password123!", "123456789!").Result; //Changes the password. Assert.IsFalse(result.Succeeded); result = _UserManager.ChangePasswordAsync(_TestUser.Id, "Password123!", "abcdefghijk").Result; //Changes the password. Assert.IsFalse(result.Succeeded); result = _UserManager.ChangePasswordAsync(_TestUser.Id, "Password123!", "abcdefghijK1!").Result; //Changes the password. Assert.IsTrue(result.Succeeded); } http://stackoverflow.com/q/26400537/11361
  • 37. Join the conversation on Twitter: @DevWeek // #DW2016 // #DevWeek How many Assert(s) per test? One Assert Per Test! Two Assert == Two Tests ๏ƒ  Usually ??? โ€(โ€ฆthe Code is more) what you'd call guidelines than actual rulesโ€
  • 38. Join the conversation on Twitter: @DevWeek // #DW2016 // #DevWeek Sometimes multiple asserts make sense [TestMethod] public void CompareTwoAsserts() { var actual = GetNextMessage(); Assert.AreEqual(1, actual.Id); Assert.AreEqual("str-1", actual.Content); }
  • 39. Join the conversation on Twitter: @DevWeek // #DW2016 // #DevWeek public class AssertAll { public static void Execute(params Action[] assertionsToRun) { var errorMessages = new List<exception>(); foreach (var action in assertionsToRun) { try { action.Invoke(); } catch (Exception exc) { errorMessages.Add(exc); } } if(errorMessages.Any()) { var separator = string.Format("{0}{0}", Environment.NewLine); string errorMessage = string.Join(separator, errorMessages); Assert.Fail(string.Format("The following conditions failed:{0}{1}", Environment.NewLine, errorMessage)); } } } http://blog.drorhelper.com/2011/02/multiple-asserts-done-right.html
  • 40. Join the conversation on Twitter: @DevWeek // #DW2016 // #DevWeek Using AssertAll [TestMethod] public void CompareTwoAsserts() { var actual = CreateMessage(); AssertAll.Execute( () => Assert.AreEqual(1, actual.Id), () => Assert.AreEqual("str-1", actual.Content); }
  • 41. Join the conversation on Twitter: @DevWeek // #DW2016 // #DevWeek Some frameworks are catching up! https://github.com/nunit/docs/wiki/Multiple-Asserts-Spec
  • 42. Join the conversation on Twitter: @DevWeek // #DW2016 // #DevWeek Ever had issues choosing the right Assert? โ€ข IsTrue vs. AreEqual โ€ข Parameter ordering confusion โ€ข StringAssert/CollectionAssert Itโ€™s all about proper error messages
  • 43. Join the conversation on Twitter: @DevWeek // #DW2016 // #DevWeek Tool: 3rd party assertion libraries ๏ƒผBetter error messages ๏ƒผReadability ๏ƒผMultiple asserts* ร—Additional dependency ร—Limited UT framework support ร—System.Object โ€œSPAMEDโ€ by extension messages
  • 44. Join the conversation on Twitter: @DevWeek // #DW2016 // #DevWeek Shouldly [Fact] public void AddTest() { var calculator = new Calculator(); var result = calculator.Add(2, 3); Assert.Equal(6, result); } [Fact] public void AddTest_Shouldly() { var calculator = new Calculator(); var result = calculator.Add(2, 3); result.ShouldBe(6); } https://github.com/shouldly/shouldly Shouldly.ShouldAssertException result should be 6 but was 5 Xunit.Sdk.EqualException Assert.Equal() Failure Expected: 6 Actual: 5
  • 45. Join the conversation on Twitter: @DevWeek // #DW2016 // #DevWeek Shouldly [Fact] public void GetDivisorsTest() { var calculator = new Calculator(); var result = calculator.GetDivisors(20); Assert.Equal(new[] {2,3,5,7}, result); } [Fact] public void GetDivisorsTest_Shouldly() { var calculator = new Calculator(); var result = calculator.GetDivisors(20); result.ShouldBe(new[] { 2, 3, 5, 7 }); } https://github.com/shouldly/shouldly Shouldly.ShouldAssertException result should be [2, 3, 5, 7] but was [2, 4, 5, 10] difference [2, *4*, 5, *10*] Xunit.Sdk.EqualException Assert.Equal() Failure Expected: Int32[] [2, 3, 5, 7] Actual: WhereEnumerableIterator<Int32> [2, 4, 5, 10]
  • 46. Join the conversation on Twitter: @DevWeek // #DW2016 // #DevWeek FluentAssertions [Fact] public void CompareTwoObjects() { var customer1 = new Customer("cust-1", "John Doe"); var customer2 = new Customer("cust-2", "John Doe"); customer1.ShouldBeEquivalentTo(customer2, o => o.Excluding(customer => customer.Id)); } http://www.fluentassertions.com/
  • 47. Join the conversation on Twitter: @DevWeek // #DW2016 // #DevWeek AssertHelper [Test] public void CheckCompare() { var myClass = new MyClass(); Expect.That(() => myClass.ReturnFive() == 10); } [Test] public void CheckTrue() { var myClass = new MyClass(); Expect.That(() => myClass.ReturnFalse() == true); } [Test] public void StringStartsWith() { var s1 = "1234567890"; Expect.That(() => s1.StartsWith("456")); } [Test] public void CollectionContains() { var c1 = new[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 0 }; Expect.That(() => c1.Contains(41)); } https://github.com/dhelper/AssertHelper
  • 48. Join the conversation on Twitter: @DevWeek // #DW2016 // #DevWeek Test organization
  • 49. Join the conversation on Twitter: @DevWeek // #DW2016 // #DevWeek Test structure issues โ€ข What to call the test? โ€ข AAA is not mandatory โ€ข What should I test? โ€ข How to avoid unreadable, complicated tests? - Unit testing framework provide no structure
  • 50. Join the conversation on Twitter: @DevWeek // #DW2016 // #DevWeek The BDD approach Step Definitions
  • 51. Join the conversation on Twitter: @DevWeek // #DW2016 // #DevWeek Specifications == focused test Feature: Addition In order to avoid silly mistakes As a math idiot I want to be told the sum of two numbers Scenario: Add two numbers Given I have entered 50 into the calculator And I have entered 70 into the calculator When I press add Then the result should be 120 on the screen
  • 52. Join the conversation on Twitter: @DevWeek // #DW2016 // #DevWeek BDD Example: SpecFlow http://www.specflow.org/
  • 53. Join the conversation on Twitter: @DevWeek // #DW2016 // #DevWeek Tool: BDDfy [TestClass] public class CardHasBeenDisabled { private Card _card; private Atm _subject; void GivenTheCardIsDisabled() { _card = new Card(false, 100); _subject = new Atm(100); } void WhenTheAccountHolderRequestsMoney() { _subject.RequestMoney(_card, 20); } void ThenTheAtmShouldRetainTheCard() { Assert.IsTrue(_subject.CardIsRetained); } void AndTheAtmShouldSayTheCardHasBeenRetained() { Assert.AreEqual(DisplayMessage.CardIsRetained, _subject.Message); } [TestMethod] public void Execute() { this.BDDfy(); } }
  • 54. Join the conversation on Twitter: @DevWeek // #DW2016 // #DevWeek Test execution
  • 55. Join the conversation on Twitter: @DevWeek // #DW2016 // #DevWeek Everybody needs a CI server Unit tests without a CI server are a waste of time - if you're running all of the tests all of the time locally you're a better man then I am
  • 56. Join the conversation on Twitter: @DevWeek // #DW2016 // #DevWeek Tool: Continuous testing DotCover Typemock Runner nCrunch
  • 57. Join the conversation on Twitter: @DevWeek // #DW2016 // #DevWeek The right tools will help you write good tests Arrange Builder Pattern AutoMocking Containers Export Assert Shouldly FluentAssertions AssertHelper Test Structure BDDfy Continuous Testing Typemock Runner DotCover nCrunch
  • 58. Join the conversation on Twitter: @DevWeek // #DW2016 // #DevWeek Thank you Dror Helper | @dhelper | http://blog.drorhelper.com

Editor's Notes

  • #4: 2003 โ€“ first attempt at unit testing 2003 + Week โ€“ Failed! 2005 โ€“ Leave job 2006 โ€“ 2nd attempt at Unit testing Failed Find job + UT + Mentor Success
  • #5: Individuals and interactionsย over processes and tools
  • #15: Automated Test Unit of Work Check Single Assumption
  • #20: Duplicate code Complex system initialization Constructor updated
  • #28: Create instances of SUT Decouples SUT from constructor Usually use DI/IoC container
  • #38: - Two asserts โ€“ no idea what caused the failure - Test is testing several things
  • #39: Explain about Using Object.Equals & Object.ToString Demo?
  • #43: - Two asserts โ€“ no idea what caused the failure Test is testing several things Left or right? InstanceOf MSTest vs. NUnit
  • #51: Organized Overhead
  • #52: Organized Overhead
  • #53: The only problem: overhead