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

PDF
Java onguice20070426
PDF
Ten Minutes To Tellurium
PDF
Easy tests with Selenide and Easyb
PPTX
The Screenplay Pattern: Better Interactions for Better Automation
KEY
SWTBot Tutorial
PDF
iOS UI Testing in Xcode
PPTX
iOS Automation: XCUITest + Gherkin
Java onguice20070426
Ten Minutes To Tellurium
Easy tests with Selenide and Easyb
The Screenplay Pattern: Better Interactions for Better Automation
SWTBot Tutorial
iOS UI Testing in Xcode
iOS Automation: XCUITest + Gherkin

What's hot (20)

PDF
Implementing Quality on a Java Project
PDF
Kiss PageObjects [01-2017]
PDF
How to setup unit testing in Android Studio
PDF
Plugin for Plugin, или расширяем Android New Build System. Антон Руткевич
PDF
Polyglot automation - QA Fest - 2015
PPT
Swtbot
PPTX
XCUITest for iOS App Testing and how to test with Xcode
PDF
Automated Xcode 7 UI Testing
PDF
React.js: You deserve to know about it
PDF
Abstraction Layers Test Management Summit Faciliated Session 2014
PPT
JsUnit
PDF
Learn How to Unit Test Your Android Application (with Robolectric)
PPTX
SwtBot: Unit Testing Made Easy
PDF
Advanced Dagger talk from 360andev
PDF
Functional Testing made easy with SWTBot for Developers and Testers
PDF
Unit testing and Android
PPTX
Robolectric Adventure
PPTX
Eyes or heart
PDF
Iasi code camp 20 april 2013 implement-quality-java-massol-codecamp
PDF
More android code puzzles
Implementing Quality on a Java Project
Kiss PageObjects [01-2017]
How to setup unit testing in Android Studio
Plugin for Plugin, или расширяем Android New Build System. Антон Руткевич
Polyglot automation - QA Fest - 2015
Swtbot
XCUITest for iOS App Testing and how to test with Xcode
Automated Xcode 7 UI Testing
React.js: You deserve to know about it
Abstraction Layers Test Management Summit Faciliated Session 2014
JsUnit
Learn How to Unit Test Your Android Application (with Robolectric)
SwtBot: Unit Testing Made Easy
Advanced Dagger talk from 360andev
Functional Testing made easy with SWTBot for Developers and Testers
Unit testing and Android
Robolectric Adventure
Eyes or heart
Iasi code camp 20 april 2013 implement-quality-java-massol-codecamp
More android code puzzles
Ad

Viewers also liked (9)

PPTX
Presentation ch 6
PPTX
Electronics 101 for software developers
PPT
азиза омарова фитнес клуб предприниматель
PPS
SEGUNDA GUERRA MUNDIAL
PPTX
PPTX
Finding PR Success on Reddit
PPTX
INDUSTRIAL TRAINING(PPT) DLW,Varanasi
PPTX
PRESENTATION ON DIESEL TRACTION CENTRE GONDA
PPTX
Loco diesel shed, pulera
Presentation ch 6
Electronics 101 for software developers
азиза омарова фитнес клуб предприниматель
SEGUNDA GUERRA MUNDIAL
Finding PR Success on Reddit
INDUSTRIAL TRAINING(PPT) DLW,Varanasi
PRESENTATION ON DIESEL TRACTION CENTRE GONDA
Loco diesel shed, pulera
Ad

Similar to Secret unit testing tools (20)

PPTX
Secret unit testing tools no one ever told you about
PDF
Djangocon 2014 angular + django
PPTX
Unit testing on mobile apps
PPTX
The secret unit testing tools no one has ever told you about
PPTX
Breaking Dependencies to Allow Unit Testing
PDF
Get Hip with JHipster - GIDS 2019
PDF
Refactor your way forward
PDF
Test-driven Development with Drupal and Codeception (DrupalCamp Brighton)
PPTX
Tdd is not about testing (OOP)
PPTX
Async task, threads, pools, and executors oh my!
PPTX
Xam expertday
PPT
Testing And Drupal
PPTX
Testing with VS2010 - A Bugs Life
PDF
Art of unit testing: how to do it right
PPTX
The secret unit testing tools no one ever told you about
PDF
Developing your own OpenStack Swift middleware
PPTX
Testing ASP.NET - Progressive.NET
PDF
Reactive Type safe Webcomponents with skateJS
PDF
Developer Tests - Things to Know
PPTX
The real beginner's guide to android testing
Secret unit testing tools no one ever told you about
Djangocon 2014 angular + django
Unit testing on mobile apps
The secret unit testing tools no one has ever told you about
Breaking Dependencies to Allow Unit Testing
Get Hip with JHipster - GIDS 2019
Refactor your way forward
Test-driven Development with Drupal and Codeception (DrupalCamp Brighton)
Tdd is not about testing (OOP)
Async task, threads, pools, and executors oh my!
Xam expertday
Testing And Drupal
Testing with VS2010 - A Bugs Life
Art of unit testing: how to do it right
The secret unit testing tools no one ever told you about
Developing your own OpenStack Swift middleware
Testing ASP.NET - Progressive.NET
Reactive Type safe Webcomponents with skateJS
Developer Tests - Things to Know
The real beginner's guide to android testing

More from Dror Helper (20)

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

Recently uploaded (20)

PDF
Navsoft: AI-Powered Business Solutions & Custom Software Development
PPTX
VVF-Customer-Presentation2025-Ver1.9.pptx
PDF
wealthsignaloriginal-com-DS-text-... (1).pdf
PDF
How to Migrate SBCGlobal Email to Yahoo Easily
PDF
AI in Product Development-omnex systems
PDF
2025 Textile ERP Trends: SAP, Odoo & Oracle
PDF
medical staffing services at VALiNTRY
PDF
PTS Company Brochure 2025 (1).pdf.......
PDF
Design an Analysis of Algorithms II-SECS-1021-03
PDF
Internet Downloader Manager (IDM) Crack 6.42 Build 42 Updates Latest 2025
PPTX
Transform Your Business with a Software ERP System
PPTX
Odoo POS Development Services by CandidRoot Solutions
PDF
Design an Analysis of Algorithms I-SECS-1021-03
PPTX
Operating system designcfffgfgggggggvggggggggg
PDF
Audit Checklist Design Aligning with ISO, IATF, and Industry Standards — Omne...
PPTX
Oracle E-Business Suite: A Comprehensive Guide for Modern Enterprises
PDF
Internet Downloader Manager (IDM) Crack 6.42 Build 41
PPTX
Introduction to Artificial Intelligence
PDF
Odoo Companies in India – Driving Business Transformation.pdf
PDF
Why TechBuilder is the Future of Pickup and Delivery App Development (1).pdf
Navsoft: AI-Powered Business Solutions & Custom Software Development
VVF-Customer-Presentation2025-Ver1.9.pptx
wealthsignaloriginal-com-DS-text-... (1).pdf
How to Migrate SBCGlobal Email to Yahoo Easily
AI in Product Development-omnex systems
2025 Textile ERP Trends: SAP, Odoo & Oracle
medical staffing services at VALiNTRY
PTS Company Brochure 2025 (1).pdf.......
Design an Analysis of Algorithms II-SECS-1021-03
Internet Downloader Manager (IDM) Crack 6.42 Build 42 Updates Latest 2025
Transform Your Business with a Software ERP System
Odoo POS Development Services by CandidRoot Solutions
Design an Analysis of Algorithms I-SECS-1021-03
Operating system designcfffgfgggggggvggggggggg
Audit Checklist Design Aligning with ISO, IATF, and Industry Standards — Omne...
Oracle E-Business Suite: A Comprehensive Guide for Modern Enterprises
Internet Downloader Manager (IDM) Crack 6.42 Build 41
Introduction to Artificial Intelligence
Odoo Companies in India – Driving Business Transformation.pdf
Why TechBuilder is the Future of Pickup and Delivery App Development (1).pdf

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