SlideShare a Scribd company logo
1 of 56
The secret unit testing tools no one ever told you about
Dror Helper (@dhelper)
Demos: https://github.com/dhelper/SecretUnitTestingToolsDemos
About.ME
Consultant @CodeValue
Developing software (professionally) since 2002
Mocking code since 2008
Clean coder & Test Driven Developer
Pluralsight Author
Blogger: http://blog.drorhelper.com
Why should I care about tools?
Background: unit testing tools
Well known unit testing tools
Server
Dev Machine
Source ControlBuild Server
Test Runner
Code
Coverage
Build Agent
Unit Testing
Framework
Isolation
Framework
?
xUnit test framework
public class BeforeAndAfter {
[SetUp]
public void Initialize() {
}
[TearDown]
public void Cleanup() {
}
[Test]
public void test1() {
}
[Test]
public void test2() {
}
}
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
Mocking Frameworks
Unit test
Code under test
DependencyFake object(s)
What Mocking framework do?
1. Create Fake objects
2. Set behavior on fake objects
3. Verify method was called
And more...
[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();
}
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]
Unit test structure
[Test]
public void MyTest()
{
}
No guidance  Fragile tests  Stop unit testing
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));
}
 Act
 Assert
Arrange
Test setup (Arrange)
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);
}
Solution: Setup/TearDown
[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);
}
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);
}
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);
}
Over extraction
[TestMethod]
public async Task LoadUser_ReputationStaysTheSame() {
var viewModel = InitializeSystem(10, 10);
await viewModel.LoadUser();
await viewModel.LoadUser();
CheckColor(Colors.White, viewModel);
}
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
};
}
Builder pattern
class UserBuilder
{
private int _id, _reputation;
private string _name, _imageUrl;
public UserBuilder() {
_id = 1;
_name = "dummy";
_imageUrl = "http://dummy.jpg";
}
User Build() {
return new User {
Id = _id, Name = _name, ImageUrl = _imageUrl, Reputation = _reputation
};
}
}
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();
Tool: AutoMocking Containers
Test Container SUT
http://blog.ploeh.dk/2013/03/11/auto-mocking-container/
New()
Configure
CreateCreate SUT
Act
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();
}
https://helpercode.com/2013/12/22/on-object-creation-and-unit-tests/
Problem: Complex inputs
• Big objects
• Deep objects
• Need for precision
• Lack of knowledge
Solution: use trivial inputs
Sometimes missing the point
Not always enough for “real test”
Solution: Serialization
Supported in most programming languages (XML, json).
Need development  testing delayed
Production code change  indefinitely delayed
Tool: Export using OzCode
Verification (Assert)
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
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
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”
Sometimes multiple asserts make sense
[TestMethod]
public void CompareTwoAsserts()
{
var actual = GetNextMessage();
Assert.AreEqual(1, actual.Id);
Assert.AreEqual("str-1", actual.Content);
}
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
Using AssertAll
[TestMethod]
public void CompareTwoAsserts()
{
var actual = CreateMessage();
AssertAll.Execute(
() => Assert.AreEqual(1, actual.Id),
() => Assert.AreEqual("str-1", actual.Content);
}
Some frameworks are catching up!
https://github.com/nunit/docs/wiki/Multiple-Asserts
Choosing the right Assert?
IsTrue vs. AreEqual
Parameter ordering confusion
StringAssert/CollectionAssert
It’s all about proper error messages
Tool: 3rd party assertion libraries
Better error messages
Readability
Multiple asserts*
×Additional dependency
×Limited UT framework support
×System.Object “SPAMED” by extension methods
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
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/
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
Test organization
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
The BDD approach
Step
Definitions
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
BDD Example: SpecFlow
http://www.specflow.org/
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();
}
}
Test execution
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
Tool: Continuous testing
DotCover
Typemock Runner
nCrunch
VS2017 (Enterprise)
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
Live Unit Testing
Dror Helper | @ dhelper | http://helpercode.com
Thank you!
Demos: https://github.com/dhelper/SecretUnitTestingToolsDemos
Secret unit testing tools no one ever told you about
Secret unit testing tools no one ever told you about

More Related Content

What's hot

Android programming -_pushing_the_limits
Android programming -_pushing_the_limitsAndroid programming -_pushing_the_limits
Android programming -_pushing_the_limitsDroidcon Berlin
 
33rd Degree 2013, Bad Tests, Good Tests
33rd Degree 2013, Bad Tests, Good Tests33rd Degree 2013, Bad Tests, Good Tests
33rd Degree 2013, Bad Tests, Good TestsTomek Kaczanowski
 
The secret unit testing tools no one ever told you about
The secret unit testing tools no one ever told you aboutThe secret unit testing tools no one ever told you about
The secret unit testing tools no one ever told you aboutDror Helper
 
201913046 wahyu septiansyah network programing
201913046 wahyu septiansyah network programing201913046 wahyu septiansyah network programing
201913046 wahyu septiansyah network programingwahyuseptiansyah
 
Code generation for alternative languages
Code generation for alternative languagesCode generation for alternative languages
Code generation for alternative languagesRafael Winterhalter
 
2012 JDays Bad Tests Good Tests
2012 JDays Bad Tests Good Tests2012 JDays Bad Tests Good Tests
2012 JDays Bad Tests Good TestsTomek Kaczanowski
 
Introduction to web programming for java and c# programmers by @drpicox
Introduction to web programming for java and c# programmers by @drpicoxIntroduction to web programming for java and c# programmers by @drpicox
Introduction to web programming for java and c# programmers by @drpicoxDavid Rodenas
 
Internet Technology (Practical Questions Paper) [CBSGS - 75:25 Pattern] {Mast...
Internet Technology (Practical Questions Paper) [CBSGS - 75:25 Pattern] {Mast...Internet Technology (Practical Questions Paper) [CBSGS - 75:25 Pattern] {Mast...
Internet Technology (Practical Questions Paper) [CBSGS - 75:25 Pattern] {Mast...Mumbai B.Sc.IT Study
 
Functional Testing for React Native Apps
Functional Testing for React Native AppsFunctional Testing for React Native Apps
Functional Testing for React Native AppsK. Matthew Dupree
 
Basic Tutorial of React for Programmers
Basic Tutorial of React for ProgrammersBasic Tutorial of React for Programmers
Basic Tutorial of React for ProgrammersDavid Rodenas
 
JavaScript Proven Practises
JavaScript Proven PractisesJavaScript Proven Practises
JavaScript Proven PractisesRobert MacLean
 
Advanced java practical semester 6_computer science
Advanced java practical semester 6_computer scienceAdvanced java practical semester 6_computer science
Advanced java practical semester 6_computer scienceNiraj Bharambe
 
Rechecking SharpDevelop: Any New Bugs?
Rechecking SharpDevelop: Any New Bugs?Rechecking SharpDevelop: Any New Bugs?
Rechecking SharpDevelop: Any New Bugs?PVS-Studio
 
JUnit Kung Fu: Getting More Out of Your Unit Tests
JUnit Kung Fu: Getting More Out of Your Unit TestsJUnit Kung Fu: Getting More Out of Your Unit Tests
JUnit Kung Fu: Getting More Out of Your Unit TestsJohn Ferguson Smart Limited
 

What's hot (20)

Android programming -_pushing_the_limits
Android programming -_pushing_the_limitsAndroid programming -_pushing_the_limits
Android programming -_pushing_the_limits
 
33rd Degree 2013, Bad Tests, Good Tests
33rd Degree 2013, Bad Tests, Good Tests33rd Degree 2013, Bad Tests, Good Tests
33rd Degree 2013, Bad Tests, Good Tests
 
How to fake_properly
How to fake_properlyHow to fake_properly
How to fake_properly
 
The secret unit testing tools no one ever told you about
The secret unit testing tools no one ever told you aboutThe secret unit testing tools no one ever told you about
The secret unit testing tools no one ever told you about
 
201913046 wahyu septiansyah network programing
201913046 wahyu septiansyah network programing201913046 wahyu septiansyah network programing
201913046 wahyu septiansyah network programing
 
Server1
Server1Server1
Server1
 
Code generation for alternative languages
Code generation for alternative languagesCode generation for alternative languages
Code generation for alternative languages
 
2012 JDays Bad Tests Good Tests
2012 JDays Bad Tests Good Tests2012 JDays Bad Tests Good Tests
2012 JDays Bad Tests Good Tests
 
Introduction to web programming for java and c# programmers by @drpicox
Introduction to web programming for java and c# programmers by @drpicoxIntroduction to web programming for java and c# programmers by @drpicox
Introduction to web programming for java and c# programmers by @drpicox
 
CDI: How do I ?
CDI: How do I ?CDI: How do I ?
CDI: How do I ?
 
Internet Technology (Practical Questions Paper) [CBSGS - 75:25 Pattern] {Mast...
Internet Technology (Practical Questions Paper) [CBSGS - 75:25 Pattern] {Mast...Internet Technology (Practical Questions Paper) [CBSGS - 75:25 Pattern] {Mast...
Internet Technology (Practical Questions Paper) [CBSGS - 75:25 Pattern] {Mast...
 
Magic methods
Magic methodsMagic methods
Magic methods
 
Functional Testing for React Native Apps
Functional Testing for React Native AppsFunctional Testing for React Native Apps
Functional Testing for React Native Apps
 
Basic Tutorial of React for Programmers
Basic Tutorial of React for ProgrammersBasic Tutorial of React for Programmers
Basic Tutorial of React for Programmers
 
JavaScript Proven Practises
JavaScript Proven PractisesJavaScript Proven Practises
JavaScript Proven Practises
 
PHP 5 Magic Methods
PHP 5 Magic MethodsPHP 5 Magic Methods
PHP 5 Magic Methods
 
Advanced java practical semester 6_computer science
Advanced java practical semester 6_computer scienceAdvanced java practical semester 6_computer science
Advanced java practical semester 6_computer science
 
GMock framework
GMock frameworkGMock framework
GMock framework
 
Rechecking SharpDevelop: Any New Bugs?
Rechecking SharpDevelop: Any New Bugs?Rechecking SharpDevelop: Any New Bugs?
Rechecking SharpDevelop: Any New Bugs?
 
JUnit Kung Fu: Getting More Out of Your Unit Tests
JUnit Kung Fu: Getting More Out of Your Unit TestsJUnit Kung Fu: Getting More Out of Your Unit Tests
JUnit Kung Fu: Getting More Out of Your Unit Tests
 

Similar to Secret unit testing tools no one ever told you about

Grails unit testing
Grails unit testingGrails unit testing
Grails unit testingpleeps
 
Secret unit testing tools
Secret unit testing toolsSecret unit testing tools
Secret unit testing toolsDror Helper
 
Security Testing
Security TestingSecurity Testing
Security TestingKiran Kumar
 
Android testing
Android testingAndroid testing
Android testingSean Tsai
 
Breaking Dependencies To Allow Unit Testing - Steve Smith | FalafelCON 2014
Breaking Dependencies To Allow Unit Testing - Steve Smith | FalafelCON 2014Breaking Dependencies To Allow Unit Testing - Steve Smith | FalafelCON 2014
Breaking Dependencies To Allow Unit Testing - Steve Smith | FalafelCON 2014FalafelSoftware
 
Breaking Dependencies to Allow Unit Testing
Breaking Dependencies to Allow Unit TestingBreaking Dependencies to Allow Unit Testing
Breaking Dependencies to Allow Unit TestingSteven Smith
 
Testing with VS2010 - A Bugs Life
Testing with VS2010 - A Bugs LifeTesting with VS2010 - A Bugs Life
Testing with VS2010 - A Bugs LifePeter Gfader
 
Testing in android
Testing in androidTesting in android
Testing in androidjtrindade
 
Solit 2013, Автоматизация тестирования сложных систем: mixed mode automated t...
Solit 2013, Автоматизация тестирования сложных систем: mixed mode automated t...Solit 2013, Автоматизация тестирования сложных систем: mixed mode automated t...
Solit 2013, Автоматизация тестирования сложных систем: mixed mode automated t...solit
 
Breaking Dependencies to Allow Unit Testing
Breaking Dependencies to Allow Unit TestingBreaking Dependencies to Allow Unit Testing
Breaking Dependencies to Allow Unit TestingSteven Smith
 
Testing ASP.NET - Progressive.NET
Testing ASP.NET - Progressive.NETTesting ASP.NET - Progressive.NET
Testing ASP.NET - Progressive.NETBen Hall
 
Testing And Drupal
Testing And DrupalTesting And Drupal
Testing And DrupalPeter Arato
 
EPHPC Webinar Slides: Unit Testing by Arthur Purnama
EPHPC Webinar Slides: Unit Testing by Arthur PurnamaEPHPC Webinar Slides: Unit Testing by Arthur Purnama
EPHPC Webinar Slides: Unit Testing by Arthur PurnamaEnterprise PHP Center
 
Code to DI For - Dependency Injection for Modern Applications
Code to DI For - Dependency Injection for Modern ApplicationsCode to DI For - Dependency Injection for Modern Applications
Code to DI For - Dependency Injection for Modern ApplicationsCaleb Jenkins
 
Тестирование и Django
Тестирование и DjangoТестирование и Django
Тестирование и DjangoMoscowDjango
 
UI-Testing - Selenium? Rich-Clients? Containers? @APEX connect 2018
UI-Testing - Selenium? Rich-Clients? Containers? @APEX connect 2018UI-Testing - Selenium? Rich-Clients? Containers? @APEX connect 2018
UI-Testing - Selenium? Rich-Clients? Containers? @APEX connect 2018Tobias Schneck
 

Similar to Secret unit testing tools no one ever told you about (20)

Grails unit testing
Grails unit testingGrails unit testing
Grails unit testing
 
Secret unit testing tools
Secret unit testing toolsSecret unit testing tools
Secret unit testing tools
 
Security Testing
Security TestingSecurity Testing
Security Testing
 
Android TDD
Android TDDAndroid TDD
Android TDD
 
Tdd & unit test
Tdd & unit testTdd & unit test
Tdd & unit test
 
Android testing
Android testingAndroid testing
Android testing
 
Breaking Dependencies To Allow Unit Testing - Steve Smith | FalafelCON 2014
Breaking Dependencies To Allow Unit Testing - Steve Smith | FalafelCON 2014Breaking Dependencies To Allow Unit Testing - Steve Smith | FalafelCON 2014
Breaking Dependencies To Allow Unit Testing - Steve Smith | FalafelCON 2014
 
Breaking Dependencies to Allow Unit Testing
Breaking Dependencies to Allow Unit TestingBreaking Dependencies to Allow Unit Testing
Breaking Dependencies to Allow Unit Testing
 
Testing with VS2010 - A Bugs Life
Testing with VS2010 - A Bugs LifeTesting with VS2010 - A Bugs Life
Testing with VS2010 - A Bugs Life
 
Testing in android
Testing in androidTesting in android
Testing in android
 
Solit 2013, Автоматизация тестирования сложных систем: mixed mode automated t...
Solit 2013, Автоматизация тестирования сложных систем: mixed mode automated t...Solit 2013, Автоматизация тестирования сложных систем: mixed mode automated t...
Solit 2013, Автоматизация тестирования сложных систем: mixed mode automated t...
 
Breaking Dependencies to Allow Unit Testing
Breaking Dependencies to Allow Unit TestingBreaking Dependencies to Allow Unit Testing
Breaking Dependencies to Allow Unit Testing
 
Testing ASP.NET - Progressive.NET
Testing ASP.NET - Progressive.NETTesting ASP.NET - Progressive.NET
Testing ASP.NET - Progressive.NET
 
Unit Testing
Unit TestingUnit Testing
Unit Testing
 
Unit testing
Unit testingUnit testing
Unit testing
 
Testing And Drupal
Testing And DrupalTesting And Drupal
Testing And Drupal
 
EPHPC Webinar Slides: Unit Testing by Arthur Purnama
EPHPC Webinar Slides: Unit Testing by Arthur PurnamaEPHPC Webinar Slides: Unit Testing by Arthur Purnama
EPHPC Webinar Slides: Unit Testing by Arthur Purnama
 
Code to DI For - Dependency Injection for Modern Applications
Code to DI For - Dependency Injection for Modern ApplicationsCode to DI For - Dependency Injection for Modern Applications
Code to DI For - Dependency Injection for Modern Applications
 
Тестирование и Django
Тестирование и DjangoТестирование и Django
Тестирование и Django
 
UI-Testing - Selenium? Rich-Clients? Containers? @APEX connect 2018
UI-Testing - Selenium? Rich-Clients? Containers? @APEX connect 2018UI-Testing - Selenium? Rich-Clients? Containers? @APEX connect 2018
UI-Testing - Selenium? Rich-Clients? Containers? @APEX connect 2018
 

More from Dror Helper

Unit testing patterns for concurrent code
Unit testing patterns for concurrent codeUnit testing patterns for concurrent code
Unit testing patterns for concurrent codeDror Helper
 
Debugging with visual studio beyond 'F5'
Debugging with visual studio beyond 'F5'Debugging with visual studio beyond 'F5'
Debugging with visual studio beyond 'F5'Dror Helper
 
From clever code to better code
From clever code to better codeFrom clever code to better code
From clever code to better codeDror Helper
 
From clever code to better code
From clever code to better codeFrom clever code to better code
From clever code to better codeDror Helper
 
A software developer guide to working with aws
A software developer guide to working with awsA software developer guide to working with aws
A software developer guide to working with awsDror Helper
 
The role of the architect in agile
The role of the architect in agileThe role of the architect in agile
The role of the architect in agileDror Helper
 
Harnessing the power of aws using dot net core
Harnessing the power of aws using dot net coreHarnessing the power of aws using dot net core
Harnessing the power of aws using dot net coreDror Helper
 
Developing multi-platform microservices using .NET core
 Developing multi-platform microservices using .NET core Developing multi-platform microservices using .NET core
Developing multi-platform microservices using .NET coreDror Helper
 
Harnessing the power of aws using dot net
Harnessing the power of aws using dot netHarnessing the power of aws using dot net
Harnessing the power of aws using dot netDror Helper
 
C++ Unit testing - the good, the bad & the ugly
C++ Unit testing - the good, the bad & the uglyC++ Unit testing - the good, the bad & the ugly
C++ Unit testing - the good, the bad & the uglyDror Helper
 
Working with c++ legacy code
Working with c++ legacy codeWorking with c++ legacy code
Working with c++ legacy codeDror Helper
 
Visual Studio tricks every dot net developer should know
Visual Studio tricks every dot net developer should knowVisual Studio tricks every dot net developer should know
Visual Studio tricks every dot net developer should knowDror Helper
 
Electronics 101 for software developers
Electronics 101 for software developersElectronics 101 for software developers
Electronics 101 for software developersDror Helper
 
Navigating the xDD Alphabet Soup
Navigating the xDD Alphabet SoupNavigating the xDD Alphabet Soup
Navigating the xDD Alphabet SoupDror Helper
 
Who’s afraid of WinDbg
Who’s afraid of WinDbgWho’s afraid of WinDbg
Who’s afraid of WinDbgDror Helper
 
Designing with tests
Designing with testsDesigning with tests
Designing with testsDror Helper
 
Building unit tests correctly with visual studio 2013
Building unit tests correctly with visual studio 2013Building unit tests correctly with visual studio 2013
Building unit tests correctly with visual studio 2013Dror Helper
 
Writing clean code in C# and .NET
Writing clean code in C# and .NETWriting clean code in C# and .NET
Writing clean code in C# and .NETDror Helper
 
Using FakeIteasy
Using FakeIteasyUsing FakeIteasy
Using FakeIteasyDror Helper
 
Battle of The Mocking Frameworks
Battle of The Mocking FrameworksBattle of The Mocking Frameworks
Battle of The Mocking FrameworksDror Helper
 

More from Dror Helper (20)

Unit testing patterns for concurrent code
Unit testing patterns for concurrent codeUnit testing patterns for concurrent code
Unit testing patterns for concurrent code
 
Debugging with visual studio beyond 'F5'
Debugging with visual studio beyond 'F5'Debugging with visual studio beyond 'F5'
Debugging with visual studio beyond 'F5'
 
From clever code to better code
From clever code to better codeFrom clever code to better code
From clever code to better code
 
From clever code to better code
From clever code to better codeFrom clever code to better code
From clever code to better code
 
A software developer guide to working with aws
A software developer guide to working with awsA software developer guide to working with aws
A software developer guide to working with aws
 
The role of the architect in agile
The role of the architect in agileThe role of the architect in agile
The role of the architect in agile
 
Harnessing the power of aws using dot net core
Harnessing the power of aws using dot net coreHarnessing the power of aws using dot net core
Harnessing the power of aws using dot net core
 
Developing multi-platform microservices using .NET core
 Developing multi-platform microservices using .NET core Developing multi-platform microservices using .NET core
Developing multi-platform microservices using .NET core
 
Harnessing the power of aws using dot net
Harnessing the power of aws using dot netHarnessing the power of aws using dot net
Harnessing the power of aws using dot net
 
C++ Unit testing - the good, the bad & the ugly
C++ Unit testing - the good, the bad & the uglyC++ Unit testing - the good, the bad & the ugly
C++ Unit testing - the good, the bad & the ugly
 
Working with c++ legacy code
Working with c++ legacy codeWorking with c++ legacy code
Working with c++ legacy code
 
Visual Studio tricks every dot net developer should know
Visual Studio tricks every dot net developer should knowVisual Studio tricks every dot net developer should know
Visual Studio tricks every dot net developer should know
 
Electronics 101 for software developers
Electronics 101 for software developersElectronics 101 for software developers
Electronics 101 for software developers
 
Navigating the xDD Alphabet Soup
Navigating the xDD Alphabet SoupNavigating the xDD Alphabet Soup
Navigating the xDD Alphabet Soup
 
Who’s afraid of WinDbg
Who’s afraid of WinDbgWho’s afraid of WinDbg
Who’s afraid of WinDbg
 
Designing with tests
Designing with testsDesigning with tests
Designing with tests
 
Building unit tests correctly with visual studio 2013
Building unit tests correctly with visual studio 2013Building unit tests correctly with visual studio 2013
Building unit tests correctly with visual studio 2013
 
Writing clean code in C# and .NET
Writing clean code in C# and .NETWriting clean code in C# and .NET
Writing clean code in C# and .NET
 
Using FakeIteasy
Using FakeIteasyUsing FakeIteasy
Using FakeIteasy
 
Battle of The Mocking Frameworks
Battle of The Mocking FrameworksBattle of The Mocking Frameworks
Battle of The Mocking Frameworks
 

Recently uploaded

Implementing Zero Trust strategy with Azure
Implementing Zero Trust strategy with AzureImplementing Zero Trust strategy with Azure
Implementing Zero Trust strategy with AzureDinusha Kumarasiri
 
Buds n Tech IT Solutions: Top-Notch Web Services in Noida
Buds n Tech IT Solutions: Top-Notch Web Services in NoidaBuds n Tech IT Solutions: Top-Notch Web Services in Noida
Buds n Tech IT Solutions: Top-Notch Web Services in Noidabntitsolutionsrishis
 
Unveiling the Future: Sylius 2.0 New Features
Unveiling the Future: Sylius 2.0 New FeaturesUnveiling the Future: Sylius 2.0 New Features
Unveiling the Future: Sylius 2.0 New FeaturesŁukasz Chruściel
 
Building a General PDE Solving Framework with Symbolic-Numeric Scientific Mac...
Building a General PDE Solving Framework with Symbolic-Numeric Scientific Mac...Building a General PDE Solving Framework with Symbolic-Numeric Scientific Mac...
Building a General PDE Solving Framework with Symbolic-Numeric Scientific Mac...stazi3110
 
ODSC - Batch to Stream workshop - integration of Apache Spark, Cassandra, Pos...
ODSC - Batch to Stream workshop - integration of Apache Spark, Cassandra, Pos...ODSC - Batch to Stream workshop - integration of Apache Spark, Cassandra, Pos...
ODSC - Batch to Stream workshop - integration of Apache Spark, Cassandra, Pos...Christina Lin
 
Building Real-Time Data Pipelines: Stream & Batch Processing workshop Slide
Building Real-Time Data Pipelines: Stream & Batch Processing workshop SlideBuilding Real-Time Data Pipelines: Stream & Batch Processing workshop Slide
Building Real-Time Data Pipelines: Stream & Batch Processing workshop SlideChristina Lin
 
办理学位证(UQ文凭证书)昆士兰大学毕业证成绩单原版一模一样
办理学位证(UQ文凭证书)昆士兰大学毕业证成绩单原版一模一样办理学位证(UQ文凭证书)昆士兰大学毕业证成绩单原版一模一样
办理学位证(UQ文凭证书)昆士兰大学毕业证成绩单原版一模一样umasea
 
Xen Safety Embedded OSS Summit April 2024 v4.pdf
Xen Safety Embedded OSS Summit April 2024 v4.pdfXen Safety Embedded OSS Summit April 2024 v4.pdf
Xen Safety Embedded OSS Summit April 2024 v4.pdfStefano Stabellini
 
React Server Component in Next.js by Hanief Utama
React Server Component in Next.js by Hanief UtamaReact Server Component in Next.js by Hanief Utama
React Server Component in Next.js by Hanief UtamaHanief Utama
 
Der Spagat zwischen BIAS und FAIRNESS (2024)
Der Spagat zwischen BIAS und FAIRNESS (2024)Der Spagat zwischen BIAS und FAIRNESS (2024)
Der Spagat zwischen BIAS und FAIRNESS (2024)OPEN KNOWLEDGE GmbH
 
英国UN学位证,北安普顿大学毕业证书1:1制作
英国UN学位证,北安普顿大学毕业证书1:1制作英国UN学位证,北安普顿大学毕业证书1:1制作
英国UN学位证,北安普顿大学毕业证书1:1制作qr0udbr0
 
What is Fashion PLM and Why Do You Need It
What is Fashion PLM and Why Do You Need ItWhat is Fashion PLM and Why Do You Need It
What is Fashion PLM and Why Do You Need ItWave PLM
 
BATTLEFIELD ORM: TIPS, TACTICS AND STRATEGIES FOR CONQUERING YOUR DATABASE
BATTLEFIELD ORM: TIPS, TACTICS AND STRATEGIES FOR CONQUERING YOUR DATABASEBATTLEFIELD ORM: TIPS, TACTICS AND STRATEGIES FOR CONQUERING YOUR DATABASE
BATTLEFIELD ORM: TIPS, TACTICS AND STRATEGIES FOR CONQUERING YOUR DATABASEOrtus Solutions, Corp
 
SuccessFactors 1H 2024 Release - Sneak-Peek by Deloitte Germany
SuccessFactors 1H 2024 Release - Sneak-Peek by Deloitte GermanySuccessFactors 1H 2024 Release - Sneak-Peek by Deloitte Germany
SuccessFactors 1H 2024 Release - Sneak-Peek by Deloitte GermanyChristoph Pohl
 
Alluxio Monthly Webinar | Cloud-Native Model Training on Distributed Data
Alluxio Monthly Webinar | Cloud-Native Model Training on Distributed DataAlluxio Monthly Webinar | Cloud-Native Model Training on Distributed Data
Alluxio Monthly Webinar | Cloud-Native Model Training on Distributed DataAlluxio, Inc.
 
GOING AOT WITH GRAALVM – DEVOXX GREECE.pdf
GOING AOT WITH GRAALVM – DEVOXX GREECE.pdfGOING AOT WITH GRAALVM – DEVOXX GREECE.pdf
GOING AOT WITH GRAALVM – DEVOXX GREECE.pdfAlina Yurenko
 
MYjobs Presentation Django-based project
MYjobs Presentation Django-based projectMYjobs Presentation Django-based project
MYjobs Presentation Django-based projectAnoyGreter
 
Russian Call Girls in Karol Bagh Aasnvi ➡️ 8264348440 💋📞 Independent Escort S...
Russian Call Girls in Karol Bagh Aasnvi ➡️ 8264348440 💋📞 Independent Escort S...Russian Call Girls in Karol Bagh Aasnvi ➡️ 8264348440 💋📞 Independent Escort S...
Russian Call Girls in Karol Bagh Aasnvi ➡️ 8264348440 💋📞 Independent Escort S...soniya singh
 
Cloud Management Software Platforms: OpenStack
Cloud Management Software Platforms: OpenStackCloud Management Software Platforms: OpenStack
Cloud Management Software Platforms: OpenStackVICTOR MAESTRE RAMIREZ
 

Recently uploaded (20)

Implementing Zero Trust strategy with Azure
Implementing Zero Trust strategy with AzureImplementing Zero Trust strategy with Azure
Implementing Zero Trust strategy with Azure
 
Buds n Tech IT Solutions: Top-Notch Web Services in Noida
Buds n Tech IT Solutions: Top-Notch Web Services in NoidaBuds n Tech IT Solutions: Top-Notch Web Services in Noida
Buds n Tech IT Solutions: Top-Notch Web Services in Noida
 
Unveiling the Future: Sylius 2.0 New Features
Unveiling the Future: Sylius 2.0 New FeaturesUnveiling the Future: Sylius 2.0 New Features
Unveiling the Future: Sylius 2.0 New Features
 
Building a General PDE Solving Framework with Symbolic-Numeric Scientific Mac...
Building a General PDE Solving Framework with Symbolic-Numeric Scientific Mac...Building a General PDE Solving Framework with Symbolic-Numeric Scientific Mac...
Building a General PDE Solving Framework with Symbolic-Numeric Scientific Mac...
 
ODSC - Batch to Stream workshop - integration of Apache Spark, Cassandra, Pos...
ODSC - Batch to Stream workshop - integration of Apache Spark, Cassandra, Pos...ODSC - Batch to Stream workshop - integration of Apache Spark, Cassandra, Pos...
ODSC - Batch to Stream workshop - integration of Apache Spark, Cassandra, Pos...
 
Hot Sexy call girls in Patel Nagar🔝 9953056974 🔝 escort Service
Hot Sexy call girls in Patel Nagar🔝 9953056974 🔝 escort ServiceHot Sexy call girls in Patel Nagar🔝 9953056974 🔝 escort Service
Hot Sexy call girls in Patel Nagar🔝 9953056974 🔝 escort Service
 
Building Real-Time Data Pipelines: Stream & Batch Processing workshop Slide
Building Real-Time Data Pipelines: Stream & Batch Processing workshop SlideBuilding Real-Time Data Pipelines: Stream & Batch Processing workshop Slide
Building Real-Time Data Pipelines: Stream & Batch Processing workshop Slide
 
办理学位证(UQ文凭证书)昆士兰大学毕业证成绩单原版一模一样
办理学位证(UQ文凭证书)昆士兰大学毕业证成绩单原版一模一样办理学位证(UQ文凭证书)昆士兰大学毕业证成绩单原版一模一样
办理学位证(UQ文凭证书)昆士兰大学毕业证成绩单原版一模一样
 
Xen Safety Embedded OSS Summit April 2024 v4.pdf
Xen Safety Embedded OSS Summit April 2024 v4.pdfXen Safety Embedded OSS Summit April 2024 v4.pdf
Xen Safety Embedded OSS Summit April 2024 v4.pdf
 
React Server Component in Next.js by Hanief Utama
React Server Component in Next.js by Hanief UtamaReact Server Component in Next.js by Hanief Utama
React Server Component in Next.js by Hanief Utama
 
Der Spagat zwischen BIAS und FAIRNESS (2024)
Der Spagat zwischen BIAS und FAIRNESS (2024)Der Spagat zwischen BIAS und FAIRNESS (2024)
Der Spagat zwischen BIAS und FAIRNESS (2024)
 
英国UN学位证,北安普顿大学毕业证书1:1制作
英国UN学位证,北安普顿大学毕业证书1:1制作英国UN学位证,北安普顿大学毕业证书1:1制作
英国UN学位证,北安普顿大学毕业证书1:1制作
 
What is Fashion PLM and Why Do You Need It
What is Fashion PLM and Why Do You Need ItWhat is Fashion PLM and Why Do You Need It
What is Fashion PLM and Why Do You Need It
 
BATTLEFIELD ORM: TIPS, TACTICS AND STRATEGIES FOR CONQUERING YOUR DATABASE
BATTLEFIELD ORM: TIPS, TACTICS AND STRATEGIES FOR CONQUERING YOUR DATABASEBATTLEFIELD ORM: TIPS, TACTICS AND STRATEGIES FOR CONQUERING YOUR DATABASE
BATTLEFIELD ORM: TIPS, TACTICS AND STRATEGIES FOR CONQUERING YOUR DATABASE
 
SuccessFactors 1H 2024 Release - Sneak-Peek by Deloitte Germany
SuccessFactors 1H 2024 Release - Sneak-Peek by Deloitte GermanySuccessFactors 1H 2024 Release - Sneak-Peek by Deloitte Germany
SuccessFactors 1H 2024 Release - Sneak-Peek by Deloitte Germany
 
Alluxio Monthly Webinar | Cloud-Native Model Training on Distributed Data
Alluxio Monthly Webinar | Cloud-Native Model Training on Distributed DataAlluxio Monthly Webinar | Cloud-Native Model Training on Distributed Data
Alluxio Monthly Webinar | Cloud-Native Model Training on Distributed Data
 
GOING AOT WITH GRAALVM – DEVOXX GREECE.pdf
GOING AOT WITH GRAALVM – DEVOXX GREECE.pdfGOING AOT WITH GRAALVM – DEVOXX GREECE.pdf
GOING AOT WITH GRAALVM – DEVOXX GREECE.pdf
 
MYjobs Presentation Django-based project
MYjobs Presentation Django-based projectMYjobs Presentation Django-based project
MYjobs Presentation Django-based project
 
Russian Call Girls in Karol Bagh Aasnvi ➡️ 8264348440 💋📞 Independent Escort S...
Russian Call Girls in Karol Bagh Aasnvi ➡️ 8264348440 💋📞 Independent Escort S...Russian Call Girls in Karol Bagh Aasnvi ➡️ 8264348440 💋📞 Independent Escort S...
Russian Call Girls in Karol Bagh Aasnvi ➡️ 8264348440 💋📞 Independent Escort S...
 
Cloud Management Software Platforms: OpenStack
Cloud Management Software Platforms: OpenStackCloud Management Software Platforms: OpenStack
Cloud Management Software Platforms: OpenStack
 

Secret unit testing tools no one ever told you about

  • 1.
  • 2. The secret unit testing tools no one ever told you about Dror Helper (@dhelper) Demos: https://github.com/dhelper/SecretUnitTestingToolsDemos
  • 3. About.ME Consultant @CodeValue Developing software (professionally) since 2002 Mocking code since 2008 Clean coder & Test Driven Developer Pluralsight Author Blogger: http://blog.drorhelper.com
  • 4. Why should I care about tools?
  • 6. Well known unit testing tools
  • 7. Server Dev Machine Source ControlBuild Server Test Runner Code Coverage Build Agent Unit Testing Framework Isolation Framework ?
  • 8. xUnit test framework public class BeforeAndAfter { [SetUp] public void Initialize() { } [TearDown] public void Cleanup() { } [Test] public void test1() { } [Test] public void test2() { } } 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
  • 9. Mocking Frameworks Unit test Code under test DependencyFake object(s)
  • 10. What Mocking framework do? 1. Create Fake objects 2. Set behavior on fake objects 3. Verify method was called And more...
  • 11. [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. 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. No guidance  Fragile tests  Stop unit testing
  • 15. 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)); }  Act  Assert Arrange
  • 17. 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); }
  • 18. Solution: Setup/TearDown [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); }
  • 19. 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); }
  • 20. 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); }
  • 21. Over extraction [TestMethod] public async Task LoadUser_ReputationStaysTheSame() { var viewModel = InitializeSystem(10, 10); await viewModel.LoadUser(); await viewModel.LoadUser(); CheckColor(Colors.White, viewModel); }
  • 22. 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 }; }
  • 23. Builder pattern class UserBuilder { private int _id, _reputation; private string _name, _imageUrl; public UserBuilder() { _id = 1; _name = "dummy"; _imageUrl = "http://dummy.jpg"; } User Build() { return new User { Id = _id, Name = _name, ImageUrl = _imageUrl, Reputation = _reputation }; } }
  • 24. 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();
  • 25. Tool: AutoMocking Containers Test Container SUT http://blog.ploeh.dk/2013/03/11/auto-mocking-container/ New() Configure CreateCreate SUT Act
  • 26. 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(); } https://helpercode.com/2013/12/22/on-object-creation-and-unit-tests/
  • 27. Problem: Complex inputs • Big objects • Deep objects • Need for precision • Lack of knowledge
  • 28. Solution: use trivial inputs Sometimes missing the point Not always enough for “real test”
  • 29. Solution: Serialization Supported in most programming languages (XML, json). Need development  testing delayed Production code change  indefinitely delayed
  • 32. 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
  • 33. 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
  • 34. 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”
  • 35. Sometimes multiple asserts make sense [TestMethod] public void CompareTwoAsserts() { var actual = GetNextMessage(); Assert.AreEqual(1, actual.Id); Assert.AreEqual("str-1", actual.Content); }
  • 36. 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
  • 37. Using AssertAll [TestMethod] public void CompareTwoAsserts() { var actual = CreateMessage(); AssertAll.Execute( () => Assert.AreEqual(1, actual.Id), () => Assert.AreEqual("str-1", actual.Content); }
  • 38. Some frameworks are catching up! https://github.com/nunit/docs/wiki/Multiple-Asserts
  • 39. Choosing the right Assert? IsTrue vs. AreEqual Parameter ordering confusion StringAssert/CollectionAssert It’s all about proper error messages
  • 40. Tool: 3rd party assertion libraries Better error messages Readability Multiple asserts* ×Additional dependency ×Limited UT framework support ×System.Object “SPAMED” by extension methods
  • 41. 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
  • 42. 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/
  • 43. 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
  • 45. 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
  • 47. 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
  • 49. 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(); } }
  • 51. 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
  • 52. Tool: Continuous testing DotCover Typemock Runner nCrunch VS2017 (Enterprise)
  • 53. 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 Live Unit Testing
  • 54. Dror Helper | @ dhelper | http://helpercode.com Thank you! Demos: https://github.com/dhelper/SecretUnitTestingToolsDemos

Editor's Notes

  1. - Two asserts – no idea what caused the failure - Test is testing several things
  2. Explain about Using Object.Equals & Object.ToString Demo?
  3. - Two asserts – no idea what caused the failure Test is testing several things Left or right? InstanceOf MSTest vs. NUnit
  4. Organized Overhead
  5. Organized Overhead
  6. The only problem: overhead