SlideShare une entreprise Scribd logo
1  sur  50
Unit testing patterns for concurrent code 
Dror Helper 
drorh@oz-code.com | @dhelper | http://blog.drorhelper.com 
Examples: https://github.com/dhelper/ConcurrentUnitTesting
About.ME 
• Senior consultant @CodeValue 
• Developing software (professionally) since 2002 
• Mocking code since 2008 
• Test Driven Developer 
• Blogger: http://blog.drorhelper.com
We live in a concurrent world! 
The free lunch is over! 
• Multi-core CPUs are the new standard 
• New(er) language constructs 
• New(ish) languages
Meanwhile in the unit testing “world” 
[Test] 
public void AddTest() 
{ 
var cut = new Calculator(); 
var result = cut.Add(2, 3); 
Assert.AreEqual(5, result); 
}
The dark art of concurrent code 
Several actions at the same time 
Hard to follow code path 
Non deterministic execution
Good unit tests must be: 
• Trustworthy 
– Consistent results 
– Only fail due to bug or requirement change 
• Maintainable 
– Robust 
– Easy to refactor 
– Simple to update 
• Readable
Concurrency test “smells” 
× Inconsistent results 
× Untraceable fail 
× Long running tests 
× Test freeze
How can we test this method 
public void Start() 
{ 
_worker = new Thread(() => { 
while (_isAlive) { 
Thread.Sleep(1000); 
var msg = _messageProvider.GetNextMessage(); 
//Do stuff 
LastMessage = msg; 
} 
}); 
_worker.Start(); 
}
Testing start take #1 
[TestMethod] 
public void ArrivingMessagePublishedTest() 
{ 
var fakeMessageProvider = A.Fake<IMessageProvider>(); 
A.CallTo(() => fakeMessageProvider.GetNextMessage()).Returns("Hello!"); 
var server = new Server(fakeMessageProvider); 
server.Start(); 
Thread.Sleep(2000); 
Assert.AreEqual("Hello!", server.LastMessage); 
}
Test smell - “Sleep” in test 
× Time based - fail/pass inconsistently 
× Test runs for too long 
× Hard to investigate failures
“In concurrent programming if 
something can happen, then sooner 
or later it will, probably at the most 
inconvenient moment” 
Paul Butcher – Seven concurrency models in seven weeks
Testing start take #2 
[TestMethod] 
public async Task ArrivingMessagePublishedTest() 
{ 
var fakeMessageProvider = A.Fake<IMessageProvider>(); 
A.CallTo(() => fakeMessageProvider.GetNextMessage()).Returns("Hello!"); 
var server = new Server(fakeMessageProvider); 
server.Start(); 
await Task.Delay(2000); 
Assert.AreEqual("Hello!", server.LastMessage); 
}
Solution: avoid concurrent code!
Pattern #1 – humble object pattern 
We extract all the logic from the hard-to-test component into a component 
that is testable via synchronous tests. 
http://xunitpatterns.com/Humble%20Object.html 
Perform Action 
Code under Test 
Start 
Humble object 
Async 
Perform action 
Assert Result 
Production 
Code
public void Start() 
{ 
_worker = new Thread(() => { 
while (_isAlive) { 
Thread.Sleep(1000); 
var msg = _messageProvider.GetNextMessage(); 
//Do stuff 
LastMessage = msg; 
} 
}); 
_worker.Start(); 
}
public void Start() 
{ 
_worker = new Thread(() => { 
while (_isAlive) { 
Thread.Sleep(1000); 
_messageHandler.HandleNextMessage(); 
} 
}); 
_worker.Start(); 
}
And finally – the test 
[TestMethod] 
public void ArrivingMessagePublishedTest() 
{ 
var fakeMessageProvider = A.Fake<IMessageProvider>(); 
A.CallTo(() => fakeMessageProvider.GetNextMessage()).Returns("Hello!"); 
var messageHandler = new MessageHandler(fakeMessageProvider); 
messageHandler.HandleNextMessage(); 
Assert.AreEqual("Hello!", messageHandler.LastMessage); 
}
Concurrency as part of program flow 
public class MessageManager 
{ 
private IMesseageQueue _messeageQueue; 
public void CreateMessage(string message) 
{ 
// Here Be Code! 
_messeageQueue.Enqueue(message); 
} 
} 
public class MessageClient 
{ 
private IMesseageQueue _messeageQueue; 
public string LastMessage { get; set; } 
private void OnMessage(object sender, EventArgs e) 
{ 
// Here Be Code! 
LastMessage = e.Message; 
} 
}
Test before – Test After 
Start 
Code under test 
Async 
Logic2 
Assert results 
Logic1 
Start Logic1 Fake Assert Results 
Start Fake Logic2 Assert Results
Testing Flow part 1 
[TestMethod] 
public void AddNewMessageProcessedMessageInQueue() 
{ 
var messeageQueue = new AsyncMesseageQueue(); 
var manager = new MessageManager(messeageQueue); 
manager.CreateNewMessage("a new message"); 
Assert.AreEqual(1, messeageQueue.Count); 
}
Testing Flow part 2 
[TestMethod] 
public void QueueRaisedNewMessageEventClientProcessEvent() 
{ 
var messeageQueue = new AsyncMesseageQueue(); 
var client = new MessageClient(messeageQueue); 
client.OnMessage(null, new MessageEventArgs("A new message")); 
Assert.AreEqual("A new message", client.LastMessage); 
}
Avoid concurrency Patterns 
The best possible solution 
No concurrency == no problems 
× Do not test some of the code 
× Not applicable in every scenario
How can we test this class? 
public class ClassWithTimer 
{ 
private Timer _timer; 
public ClassWithTimer(Timer timer) 
{ 
_timer = timer; 
_timer.Elapsed += OnTimerElapsed; 
_timer.Start(); 
} 
private void OnTimerElapsed(object sender, ElapsedEventArgs e) 
{ 
SomethingImportantHappened = true; 
} 
public bool SomethingImportantHappened { get; private set; } 
}
Not a good idea 
[TestMethod] 
public void ThisIsABadTest() 
{ 
var timer = new Timer(1); 
var cut = new ClassWithTimer(timer); 
Thread.Sleep(100); 
Assert.IsTrue(cut.SomethingImportantHappened); 
}
Set timeout/interval to 1 
Also seen with a very small number (or zero) 
Usually done when need to wait for next tick/timeout 
× Time based == fragile/inconsistent test 
× Hard to investigate failures 
× Usually comes with Thread.Sleep
Fake & Sync 
Test 
Code under Test 
Fake 
Logic 
Assert Results
Using Typemock Isolator to fake Timer 
[TestMethod, Isolated] 
public void ThisIsAGoodTest() 
{ 
var fakeTimer = Isolate.Fake.Instance<Timer>(); 
var cut = new ClassWithTimer(fakeTimer); 
var fakeEventArgs = Isolate.Fake.Instance<ElapsedEventArgs>(); 
Isolate.Invoke.Event( 
() => fakeTimer.Elapsed += null, this, fakeEventArgs); 
Assert.IsTrue(cut.SomethingImportantHappened); 
}
Unfortunately not everything can be faked 
• Mocking tool limitation (example: inheritance based) 
• Programming language attributes 
• Special cases (example: MSCorlib) 
Solution – wrap the unfakeable 
× Problem – it requires code change
Wrapping Threadpool 
public class ThreadPoolWrapper 
{ 
public static void QueueUserWorkItem(WaitCallback callback) 
{ 
ThreadPool.QueueUserWorkItem(callback); 
} 
}
Wrapping Threadpool 
public class ClassWithWrappedThreadpool 
{ 
public void RunInThread() 
{ 
ThreadPool.QueueUserWorkItem(_ => 
{ 
SomethingImportantHappened = true; 
}); 
} 
public bool SomethingImportantHappened { get; private set; } 
} 
ThreadPoolWrapper.QueueUserWorkItem(_ =>
Testing with new ThreadpoolWrapper 
[TestClass] 
public class WorkingWithThreadpool 
{ 
[TestMethod, Isolated] 
public void UsingWrapperTest() 
{ 
Isolate.WhenCalled(() => ThreadPoolWrapper.QueueUserWorkItem(null)) 
.DoInstead(ctx => ((WaitCallback)ctx.Parameters[0]).Invoke(null)); 
var cut = new ClassWithWrappedThreadpool(); 
cut.RunInThread(); 
Assert.IsTrue(cut.SomethingImportantHappened); 
} 
}
How can we test that an 
asynchronous operation 
never happens?
Test Code Under Test 
Is Test 
Async 
Deterministic Assert Results 
Run in sync
Another day – another class to test 
public void Start() 
{ 
_cancellationTokenSource = new CancellationTokenSource(); 
Task.Run(() => 
{ 
var message = _messageBus.GetNextMessage(); 
if(message == null) 
return; 
// Do work 
if (OnNewMessage != null) 
{ 
OnNewMessage(this, EventArgs.Empty); 
} 
}, _cancellationTokenSource.Token); 
}
Switching code to “test mode” 
• Dependency injection 
• Preprocessor directives 
• Pass delegate 
• Other
Run in single thread patterns 
• Fake & Sync 
• Async code  sync test
Synchronized run patterns 
When you have to run a concurrent test in a predictable way
The Signaled pattern 
Start 
Run 
Code under test 
Signal 
Fake object 
Call 
Wait Assert result
Using the Signaled pattern 
public void DiffcultCalcAsync(int a, int b) 
{ 
Task.Run(() => 
{ 
Result = a + b; 
_otherClass.DoSomething(Result); 
}); 
}
Using the Signaled pattern 
[TestMethod] 
public void TestUsingSignal() 
{ 
var waitHandle = new ManualResetEventSlim(false); 
var fakeOtherClass = A.Fake<IOtherClass>(); 
A.CallTo(() => fakeOtherClass.DoSomething(A<int>._)).Invokes(waitHandle.Set); 
var cut = new ClassWithAsyncOperation(fakeOtherClass); 
cut.DiffcultCalcAsync(2, 3); 
var wasCalled = waitHandle.Wait(10000); 
Assert.IsTrue(wasCalled, "OtherClass.DoSomething was never called"); 
Assert.AreEqual(5, cut.Result); 
}
Busy Assert 
Start 
Run 
Code under 
test 
Assert or 
Timeout
Busy assertion 
[TestMethod] 
public void DifficultCalculationTest() 
{ 
var cut = new ClassWithAsyncOperation(); 
cut.RunAsync(2, 3); 
AssertHelper.BusyAssert(() => cut.Result == 5, 50, 100, "fail!"); 
}
Synchronized test patterns 
× Harder to investigate failures 
× Cannot test that a call was not made 
Test runs for too long but only when it fails 
 Use if other patterns are not applicable
Unit testing for concurrency issues 
Because concurrency (and async) needs to be tested as well
Test for async 
Start Method under test 
Fake object 
wait 
Assert results
Test for Deadlock 
Start 
Execute 
Code under 
test 
Thread 
WWaaitit Assert result 
Call Thread
[TestMethod, Timeout(5000)] 
public void CheckForDeadlock() 
{ 
var fakeDependency1 = A.Fake<IDependency>(); 
var fakeDependency2 = A.Fake<IDependency>(); 
var waitHandle = new ManualResetEvent(false); 
var cut = new ClassWithDeadlock(fakeDependency1, fakeDependency2); 
A.CallTo(() => fakeDependency1.Call()).Invokes(() => waitHandle.WaitOne()); 
A.CallTo(() => fakeDependency2.Call()).Invokes(() => waitHandle.WaitOne()); 
var t1 = RunInOtherThread(() => cut.Call1Then2()); 
var t2 = RunInOtherThread(() => cut.Call2Then1()); 
waitHandle.Set(); 
t1.Join(); 
t2.Join(); 
} 
T1 
T2 
L1 
L2
Avoid 
Concurrency 
Humble 
object 
Test before – 
test after 
Run in single 
thread 
Fake & Sync 
Async in 
production - 
sync in test 
Synchronize 
test 
The Signaled 
pattern 
Busy 
assertion 
Concurrency 
tests 
Test for 
Deadlock 
Test for non 
blocking 
Concurrent unit testing patterns
Conclusion 
It is possible to test concurrent code 
Avoid concurrency 
Run in single thread 
Synchronize test
Dror Helper 
C: 972.50.7668543 
e: drorh@codevalue.net 
B: blog.drorhelper.com 
w: www.codevalue.net

Contenu connexe

Tendances

shrinath updated genesys resume
shrinath updated genesys resumeshrinath updated genesys resume
shrinath updated genesys resumeShrinath M
 
Temenos- Fiorano T24 Integration
Temenos- Fiorano T24 IntegrationTemenos- Fiorano T24 Integration
Temenos- Fiorano T24 IntegrationAshraf Imran
 
Malware analysis using volatility
Malware analysis using volatilityMalware analysis using volatility
Malware analysis using volatilityYashashree Gund
 
Scalable Service-Oriented Middleware over IP
Scalable Service-Oriented Middleware over IPScalable Service-Oriented Middleware over IP
Scalable Service-Oriented Middleware over IPDai Yang
 
Instantly tradeable NFT contracts based on ERC-1155 standard
Instantly tradeable NFT contracts based on ERC-1155 standardInstantly tradeable NFT contracts based on ERC-1155 standard
Instantly tradeable NFT contracts based on ERC-1155 standardGene Leybzon
 
네트웍 설정 오류로 인한 RAC 시스템 성능 저하_Maxgauge case study
네트웍 설정 오류로 인한 RAC 시스템 성능 저하_Maxgauge case study네트웍 설정 오류로 인한 RAC 시스템 성능 저하_Maxgauge case study
네트웍 설정 오류로 인한 RAC 시스템 성능 저하_Maxgauge case study엑셈
 
Office automation system report
Office automation system reportOffice automation system report
Office automation system reportAmit Kulkarni
 
Oracle APEX, Low Code for Data Driving Apps
Oracle APEX, Low Code for Data Driving AppsOracle APEX, Low Code for Data Driving Apps
Oracle APEX, Low Code for Data Driving AppsFranco Ucci
 
Customer Contact DB Development Project
Customer Contact DB Development ProjectCustomer Contact DB Development Project
Customer Contact DB Development ProjectNicholai Stevens
 
Introduction to DIAMETER
Introduction to DIAMETERIntroduction to DIAMETER
Introduction to DIAMETERHossein Yavari
 
Chat Application [Full Documentation]
Chat Application [Full Documentation]Chat Application [Full Documentation]
Chat Application [Full Documentation]Rajon
 
Oracle EPM - Life cycle management
Oracle EPM - Life cycle managementOracle EPM - Life cycle management
Oracle EPM - Life cycle managementnking821
 

Tendances (17)

Document management on Tally.ERP 9
Document management on Tally.ERP 9 Document management on Tally.ERP 9
Document management on Tally.ERP 9
 
shrinath updated genesys resume
shrinath updated genesys resumeshrinath updated genesys resume
shrinath updated genesys resume
 
Temenos- Fiorano T24 Integration
Temenos- Fiorano T24 IntegrationTemenos- Fiorano T24 Integration
Temenos- Fiorano T24 Integration
 
Malware analysis using volatility
Malware analysis using volatilityMalware analysis using volatility
Malware analysis using volatility
 
Scalable Service-Oriented Middleware over IP
Scalable Service-Oriented Middleware over IPScalable Service-Oriented Middleware over IP
Scalable Service-Oriented Middleware over IP
 
Instantly tradeable NFT contracts based on ERC-1155 standard
Instantly tradeable NFT contracts based on ERC-1155 standardInstantly tradeable NFT contracts based on ERC-1155 standard
Instantly tradeable NFT contracts based on ERC-1155 standard
 
네트웍 설정 오류로 인한 RAC 시스템 성능 저하_Maxgauge case study
네트웍 설정 오류로 인한 RAC 시스템 성능 저하_Maxgauge case study네트웍 설정 오류로 인한 RAC 시스템 성능 저하_Maxgauge case study
네트웍 설정 오류로 인한 RAC 시스템 성능 저하_Maxgauge case study
 
Office automation system report
Office automation system reportOffice automation system report
Office automation system report
 
Oracle APEX, Low Code for Data Driving Apps
Oracle APEX, Low Code for Data Driving AppsOracle APEX, Low Code for Data Driving Apps
Oracle APEX, Low Code for Data Driving Apps
 
CCPulse Genesys
CCPulse GenesysCCPulse Genesys
CCPulse Genesys
 
Customer Contact DB Development Project
Customer Contact DB Development ProjectCustomer Contact DB Development Project
Customer Contact DB Development Project
 
Web developnment
Web developnment Web developnment
Web developnment
 
Introduction to DIAMETER
Introduction to DIAMETERIntroduction to DIAMETER
Introduction to DIAMETER
 
Final presentation on chatbot
Final presentation on chatbotFinal presentation on chatbot
Final presentation on chatbot
 
Mule Integration with Atlassian JIRA
Mule Integration with Atlassian JIRAMule Integration with Atlassian JIRA
Mule Integration with Atlassian JIRA
 
Chat Application [Full Documentation]
Chat Application [Full Documentation]Chat Application [Full Documentation]
Chat Application [Full Documentation]
 
Oracle EPM - Life cycle management
Oracle EPM - Life cycle managementOracle EPM - Life cycle management
Oracle EPM - Life cycle management
 

Similaire à Unit testing patterns for concurrent code

Unit testing patterns for concurrent code
Unit testing patterns for concurrent codeUnit testing patterns for concurrent code
Unit testing patterns for concurrent codeDror Helper
 
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
 
2012 JDays Bad Tests Good Tests
2012 JDays Bad Tests Good Tests2012 JDays Bad Tests Good Tests
2012 JDays Bad Tests Good TestsTomek Kaczanowski
 
Secret unit testing tools no one ever told you about
Secret unit testing tools no one ever told you aboutSecret unit testing tools no one ever told you about
Secret unit testing tools no one ever told you aboutDror Helper
 
Unit testing in iOS featuring OCUnit, GHUnit & OCMock
Unit testing in iOS featuring OCUnit, GHUnit & OCMockUnit testing in iOS featuring OCUnit, GHUnit & OCMock
Unit testing in iOS featuring OCUnit, GHUnit & OCMockRobot Media
 
The secret unit testing tools no one has ever told you about
The secret unit testing tools no one has ever told you aboutThe secret unit testing tools no one has ever told you about
The secret unit testing tools no one has ever told you aboutDror Helper
 
Testing in android
Testing in androidTesting in android
Testing in androidjtrindade
 
Developer Test - Things to Know
Developer Test - Things to KnowDeveloper Test - Things to Know
Developer Test - Things to Knowvilniusjug
 
An introduction to Test Driven Development on MapReduce
An introduction to Test Driven Development on MapReduceAn introduction to Test Driven Development on MapReduce
An introduction to Test Driven Development on MapReduceAnanth PackkilDurai
 
Java Concurrency, Memory Model, and Trends
Java Concurrency, Memory Model, and TrendsJava Concurrency, Memory Model, and Trends
Java Concurrency, Memory Model, and TrendsCarol McDonald
 
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
 
"Unit Testing for Mobile App" by Fandy Gotama (OLX Indonesia)
"Unit Testing for Mobile App" by Fandy Gotama  (OLX Indonesia)"Unit Testing for Mobile App" by Fandy Gotama  (OLX Indonesia)
"Unit Testing for Mobile App" by Fandy Gotama (OLX Indonesia)Tech in Asia ID
 
Tech In Asia PDC 2017 - Best practice unit testing in mobile apps
Tech In Asia PDC 2017 - Best practice unit testing in mobile appsTech In Asia PDC 2017 - Best practice unit testing in mobile apps
Tech In Asia PDC 2017 - Best practice unit testing in mobile appsFandy Gotama
 
Grails unit testing
Grails unit testingGrails unit testing
Grails unit testingpleeps
 
GeeCON 2012 Bad Tests, Good Tests
GeeCON 2012 Bad Tests, Good TestsGeeCON 2012 Bad Tests, Good Tests
GeeCON 2012 Bad Tests, Good TestsTomek Kaczanowski
 

Similaire à Unit testing patterns for concurrent code (20)

Unit testing patterns for concurrent code
Unit testing patterns for concurrent codeUnit testing patterns for concurrent code
Unit testing patterns for concurrent code
 
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
 
2012 JDays Bad Tests Good Tests
2012 JDays Bad Tests Good Tests2012 JDays Bad Tests Good Tests
2012 JDays Bad Tests Good Tests
 
Secret unit testing tools no one ever told you about
Secret unit testing tools no one ever told you aboutSecret unit testing tools no one ever told you about
Secret unit testing tools no one ever told you about
 
Unit testing in iOS featuring OCUnit, GHUnit & OCMock
Unit testing in iOS featuring OCUnit, GHUnit & OCMockUnit testing in iOS featuring OCUnit, GHUnit & OCMock
Unit testing in iOS featuring OCUnit, GHUnit & OCMock
 
The secret unit testing tools no one has ever told you about
The secret unit testing tools no one has ever told you aboutThe secret unit testing tools no one has ever told you about
The secret unit testing tools no one has ever told you about
 
Testing in android
Testing in androidTesting in android
Testing in android
 
Test driven development
Test driven developmentTest driven development
Test driven development
 
Developer Test - Things to Know
Developer Test - Things to KnowDeveloper Test - Things to Know
Developer Test - Things to Know
 
An introduction to Test Driven Development on MapReduce
An introduction to Test Driven Development on MapReduceAn introduction to Test Driven Development on MapReduce
An introduction to Test Driven Development on MapReduce
 
Qunit Java script Un
Qunit Java script UnQunit Java script Un
Qunit Java script Un
 
Java Concurrency, Memory Model, and Trends
Java Concurrency, Memory Model, and TrendsJava Concurrency, Memory Model, and Trends
Java Concurrency, Memory Model, and Trends
 
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
 
"Unit Testing for Mobile App" by Fandy Gotama (OLX Indonesia)
"Unit Testing for Mobile App" by Fandy Gotama  (OLX Indonesia)"Unit Testing for Mobile App" by Fandy Gotama  (OLX Indonesia)
"Unit Testing for Mobile App" by Fandy Gotama (OLX Indonesia)
 
Tech In Asia PDC 2017 - Best practice unit testing in mobile apps
Tech In Asia PDC 2017 - Best practice unit testing in mobile appsTech In Asia PDC 2017 - Best practice unit testing in mobile apps
Tech In Asia PDC 2017 - Best practice unit testing in mobile apps
 
Grails unit testing
Grails unit testingGrails unit testing
Grails unit testing
 
Curator intro
Curator introCurator intro
Curator intro
 
Rx workshop
Rx workshopRx workshop
Rx workshop
 
GeeCON 2012 Bad Tests, Good Tests
GeeCON 2012 Bad Tests, Good TestsGeeCON 2012 Bad Tests, Good Tests
GeeCON 2012 Bad Tests, Good Tests
 
Java Concurrency
Java ConcurrencyJava Concurrency
Java Concurrency
 

Plus de Dror 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
 
Secret unit testing tools
Secret unit testing toolsSecret unit testing tools
Secret unit testing toolsDror 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
 
Building unit tests correctly
Building unit tests correctlyBuilding unit tests correctly
Building unit tests correctlyDror 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
 

Plus de Dror Helper (20)

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
 
Secret unit testing tools
Secret unit testing toolsSecret unit testing tools
Secret unit testing tools
 
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
 
Building unit tests correctly
Building unit tests correctlyBuilding unit tests correctly
Building unit tests correctly
 
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
 

Dernier

Powerful Google developer tools for immediate impact! (2023-24 C)
Powerful Google developer tools for immediate impact! (2023-24 C)Powerful Google developer tools for immediate impact! (2023-24 C)
Powerful Google developer tools for immediate impact! (2023-24 C)wesley chun
 
Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024
Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024
Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024The Digital Insurer
 
Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...
Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...
Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...apidays
 
presentation ICT roal in 21st century education
presentation ICT roal in 21st century educationpresentation ICT roal in 21st century education
presentation ICT roal in 21st century educationjfdjdjcjdnsjd
 
Cloud Frontiers: A Deep Dive into Serverless Spatial Data and FME
Cloud Frontiers:  A Deep Dive into Serverless Spatial Data and FMECloud Frontiers:  A Deep Dive into Serverless Spatial Data and FME
Cloud Frontiers: A Deep Dive into Serverless Spatial Data and FMESafe Software
 
Manulife - Insurer Innovation Award 2024
Manulife - Insurer Innovation Award 2024Manulife - Insurer Innovation Award 2024
Manulife - Insurer Innovation Award 2024The Digital Insurer
 
Strategies for Landing an Oracle DBA Job as a Fresher
Strategies for Landing an Oracle DBA Job as a FresherStrategies for Landing an Oracle DBA Job as a Fresher
Strategies for Landing an Oracle DBA Job as a FresherRemote DBA Services
 
ProductAnonymous-April2024-WinProductDiscovery-MelissaKlemke
ProductAnonymous-April2024-WinProductDiscovery-MelissaKlemkeProductAnonymous-April2024-WinProductDiscovery-MelissaKlemke
ProductAnonymous-April2024-WinProductDiscovery-MelissaKlemkeProduct Anonymous
 
Repurposing LNG terminals for Hydrogen Ammonia: Feasibility and Cost Saving
Repurposing LNG terminals for Hydrogen Ammonia: Feasibility and Cost SavingRepurposing LNG terminals for Hydrogen Ammonia: Feasibility and Cost Saving
Repurposing LNG terminals for Hydrogen Ammonia: Feasibility and Cost SavingEdi Saputra
 
Tata AIG General Insurance Company - Insurer Innovation Award 2024
Tata AIG General Insurance Company - Insurer Innovation Award 2024Tata AIG General Insurance Company - Insurer Innovation Award 2024
Tata AIG General Insurance Company - Insurer Innovation Award 2024The Digital Insurer
 
HTML Injection Attacks: Impact and Mitigation Strategies
HTML Injection Attacks: Impact and Mitigation StrategiesHTML Injection Attacks: Impact and Mitigation Strategies
HTML Injection Attacks: Impact and Mitigation StrategiesBoston Institute of Analytics
 
Apidays New York 2024 - The value of a flexible API Management solution for O...
Apidays New York 2024 - The value of a flexible API Management solution for O...Apidays New York 2024 - The value of a flexible API Management solution for O...
Apidays New York 2024 - The value of a flexible API Management solution for O...apidays
 
Apidays New York 2024 - Scaling API-first by Ian Reasor and Radu Cotescu, Adobe
Apidays New York 2024 - Scaling API-first by Ian Reasor and Radu Cotescu, AdobeApidays New York 2024 - Scaling API-first by Ian Reasor and Radu Cotescu, Adobe
Apidays New York 2024 - Scaling API-first by Ian Reasor and Radu Cotescu, Adobeapidays
 
AWS Community Day CPH - Three problems of Terraform
AWS Community Day CPH - Three problems of TerraformAWS Community Day CPH - Three problems of Terraform
AWS Community Day CPH - Three problems of TerraformAndrey Devyatkin
 
Real Time Object Detection Using Open CV
Real Time Object Detection Using Open CVReal Time Object Detection Using Open CV
Real Time Object Detection Using Open CVKhem
 
Exploring the Future Potential of AI-Enabled Smartphone Processors
Exploring the Future Potential of AI-Enabled Smartphone ProcessorsExploring the Future Potential of AI-Enabled Smartphone Processors
Exploring the Future Potential of AI-Enabled Smartphone Processorsdebabhi2
 
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...Miguel Araújo
 
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...Drew Madelung
 
How to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected WorkerHow to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected WorkerThousandEyes
 

Dernier (20)

Powerful Google developer tools for immediate impact! (2023-24 C)
Powerful Google developer tools for immediate impact! (2023-24 C)Powerful Google developer tools for immediate impact! (2023-24 C)
Powerful Google developer tools for immediate impact! (2023-24 C)
 
Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024
Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024
Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024
 
Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...
Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...
Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...
 
presentation ICT roal in 21st century education
presentation ICT roal in 21st century educationpresentation ICT roal in 21st century education
presentation ICT roal in 21st century education
 
Cloud Frontiers: A Deep Dive into Serverless Spatial Data and FME
Cloud Frontiers:  A Deep Dive into Serverless Spatial Data and FMECloud Frontiers:  A Deep Dive into Serverless Spatial Data and FME
Cloud Frontiers: A Deep Dive into Serverless Spatial Data and FME
 
Manulife - Insurer Innovation Award 2024
Manulife - Insurer Innovation Award 2024Manulife - Insurer Innovation Award 2024
Manulife - Insurer Innovation Award 2024
 
Strategies for Landing an Oracle DBA Job as a Fresher
Strategies for Landing an Oracle DBA Job as a FresherStrategies for Landing an Oracle DBA Job as a Fresher
Strategies for Landing an Oracle DBA Job as a Fresher
 
ProductAnonymous-April2024-WinProductDiscovery-MelissaKlemke
ProductAnonymous-April2024-WinProductDiscovery-MelissaKlemkeProductAnonymous-April2024-WinProductDiscovery-MelissaKlemke
ProductAnonymous-April2024-WinProductDiscovery-MelissaKlemke
 
Repurposing LNG terminals for Hydrogen Ammonia: Feasibility and Cost Saving
Repurposing LNG terminals for Hydrogen Ammonia: Feasibility and Cost SavingRepurposing LNG terminals for Hydrogen Ammonia: Feasibility and Cost Saving
Repurposing LNG terminals for Hydrogen Ammonia: Feasibility and Cost Saving
 
Tata AIG General Insurance Company - Insurer Innovation Award 2024
Tata AIG General Insurance Company - Insurer Innovation Award 2024Tata AIG General Insurance Company - Insurer Innovation Award 2024
Tata AIG General Insurance Company - Insurer Innovation Award 2024
 
HTML Injection Attacks: Impact and Mitigation Strategies
HTML Injection Attacks: Impact and Mitigation StrategiesHTML Injection Attacks: Impact and Mitigation Strategies
HTML Injection Attacks: Impact and Mitigation Strategies
 
Apidays New York 2024 - The value of a flexible API Management solution for O...
Apidays New York 2024 - The value of a flexible API Management solution for O...Apidays New York 2024 - The value of a flexible API Management solution for O...
Apidays New York 2024 - The value of a flexible API Management solution for O...
 
Apidays New York 2024 - Scaling API-first by Ian Reasor and Radu Cotescu, Adobe
Apidays New York 2024 - Scaling API-first by Ian Reasor and Radu Cotescu, AdobeApidays New York 2024 - Scaling API-first by Ian Reasor and Radu Cotescu, Adobe
Apidays New York 2024 - Scaling API-first by Ian Reasor and Radu Cotescu, Adobe
 
AWS Community Day CPH - Three problems of Terraform
AWS Community Day CPH - Three problems of TerraformAWS Community Day CPH - Three problems of Terraform
AWS Community Day CPH - Three problems of Terraform
 
Real Time Object Detection Using Open CV
Real Time Object Detection Using Open CVReal Time Object Detection Using Open CV
Real Time Object Detection Using Open CV
 
Exploring the Future Potential of AI-Enabled Smartphone Processors
Exploring the Future Potential of AI-Enabled Smartphone ProcessorsExploring the Future Potential of AI-Enabled Smartphone Processors
Exploring the Future Potential of AI-Enabled Smartphone Processors
 
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
 
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
 
+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...
+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...
+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...
 
How to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected WorkerHow to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected Worker
 

Unit testing patterns for concurrent code

  • 1. Unit testing patterns for concurrent code Dror Helper drorh@oz-code.com | @dhelper | http://blog.drorhelper.com Examples: https://github.com/dhelper/ConcurrentUnitTesting
  • 2. About.ME • Senior consultant @CodeValue • Developing software (professionally) since 2002 • Mocking code since 2008 • Test Driven Developer • Blogger: http://blog.drorhelper.com
  • 3. We live in a concurrent world! The free lunch is over! • Multi-core CPUs are the new standard • New(er) language constructs • New(ish) languages
  • 4. Meanwhile in the unit testing “world” [Test] public void AddTest() { var cut = new Calculator(); var result = cut.Add(2, 3); Assert.AreEqual(5, result); }
  • 5. The dark art of concurrent code Several actions at the same time Hard to follow code path Non deterministic execution
  • 6. Good unit tests must be: • Trustworthy – Consistent results – Only fail due to bug or requirement change • Maintainable – Robust – Easy to refactor – Simple to update • Readable
  • 7. Concurrency test “smells” × Inconsistent results × Untraceable fail × Long running tests × Test freeze
  • 8. How can we test this method public void Start() { _worker = new Thread(() => { while (_isAlive) { Thread.Sleep(1000); var msg = _messageProvider.GetNextMessage(); //Do stuff LastMessage = msg; } }); _worker.Start(); }
  • 9. Testing start take #1 [TestMethod] public void ArrivingMessagePublishedTest() { var fakeMessageProvider = A.Fake<IMessageProvider>(); A.CallTo(() => fakeMessageProvider.GetNextMessage()).Returns("Hello!"); var server = new Server(fakeMessageProvider); server.Start(); Thread.Sleep(2000); Assert.AreEqual("Hello!", server.LastMessage); }
  • 10. Test smell - “Sleep” in test × Time based - fail/pass inconsistently × Test runs for too long × Hard to investigate failures
  • 11. “In concurrent programming if something can happen, then sooner or later it will, probably at the most inconvenient moment” Paul Butcher – Seven concurrency models in seven weeks
  • 12. Testing start take #2 [TestMethod] public async Task ArrivingMessagePublishedTest() { var fakeMessageProvider = A.Fake<IMessageProvider>(); A.CallTo(() => fakeMessageProvider.GetNextMessage()).Returns("Hello!"); var server = new Server(fakeMessageProvider); server.Start(); await Task.Delay(2000); Assert.AreEqual("Hello!", server.LastMessage); }
  • 14. Pattern #1 – humble object pattern We extract all the logic from the hard-to-test component into a component that is testable via synchronous tests. http://xunitpatterns.com/Humble%20Object.html Perform Action Code under Test Start Humble object Async Perform action Assert Result Production Code
  • 15. public void Start() { _worker = new Thread(() => { while (_isAlive) { Thread.Sleep(1000); var msg = _messageProvider.GetNextMessage(); //Do stuff LastMessage = msg; } }); _worker.Start(); }
  • 16. public void Start() { _worker = new Thread(() => { while (_isAlive) { Thread.Sleep(1000); _messageHandler.HandleNextMessage(); } }); _worker.Start(); }
  • 17. And finally – the test [TestMethod] public void ArrivingMessagePublishedTest() { var fakeMessageProvider = A.Fake<IMessageProvider>(); A.CallTo(() => fakeMessageProvider.GetNextMessage()).Returns("Hello!"); var messageHandler = new MessageHandler(fakeMessageProvider); messageHandler.HandleNextMessage(); Assert.AreEqual("Hello!", messageHandler.LastMessage); }
  • 18. Concurrency as part of program flow public class MessageManager { private IMesseageQueue _messeageQueue; public void CreateMessage(string message) { // Here Be Code! _messeageQueue.Enqueue(message); } } public class MessageClient { private IMesseageQueue _messeageQueue; public string LastMessage { get; set; } private void OnMessage(object sender, EventArgs e) { // Here Be Code! LastMessage = e.Message; } }
  • 19. Test before – Test After Start Code under test Async Logic2 Assert results Logic1 Start Logic1 Fake Assert Results Start Fake Logic2 Assert Results
  • 20. Testing Flow part 1 [TestMethod] public void AddNewMessageProcessedMessageInQueue() { var messeageQueue = new AsyncMesseageQueue(); var manager = new MessageManager(messeageQueue); manager.CreateNewMessage("a new message"); Assert.AreEqual(1, messeageQueue.Count); }
  • 21. Testing Flow part 2 [TestMethod] public void QueueRaisedNewMessageEventClientProcessEvent() { var messeageQueue = new AsyncMesseageQueue(); var client = new MessageClient(messeageQueue); client.OnMessage(null, new MessageEventArgs("A new message")); Assert.AreEqual("A new message", client.LastMessage); }
  • 22. Avoid concurrency Patterns The best possible solution No concurrency == no problems × Do not test some of the code × Not applicable in every scenario
  • 23. How can we test this class? public class ClassWithTimer { private Timer _timer; public ClassWithTimer(Timer timer) { _timer = timer; _timer.Elapsed += OnTimerElapsed; _timer.Start(); } private void OnTimerElapsed(object sender, ElapsedEventArgs e) { SomethingImportantHappened = true; } public bool SomethingImportantHappened { get; private set; } }
  • 24. Not a good idea [TestMethod] public void ThisIsABadTest() { var timer = new Timer(1); var cut = new ClassWithTimer(timer); Thread.Sleep(100); Assert.IsTrue(cut.SomethingImportantHappened); }
  • 25. Set timeout/interval to 1 Also seen with a very small number (or zero) Usually done when need to wait for next tick/timeout × Time based == fragile/inconsistent test × Hard to investigate failures × Usually comes with Thread.Sleep
  • 26. Fake & Sync Test Code under Test Fake Logic Assert Results
  • 27. Using Typemock Isolator to fake Timer [TestMethod, Isolated] public void ThisIsAGoodTest() { var fakeTimer = Isolate.Fake.Instance<Timer>(); var cut = new ClassWithTimer(fakeTimer); var fakeEventArgs = Isolate.Fake.Instance<ElapsedEventArgs>(); Isolate.Invoke.Event( () => fakeTimer.Elapsed += null, this, fakeEventArgs); Assert.IsTrue(cut.SomethingImportantHappened); }
  • 28. Unfortunately not everything can be faked • Mocking tool limitation (example: inheritance based) • Programming language attributes • Special cases (example: MSCorlib) Solution – wrap the unfakeable × Problem – it requires code change
  • 29. Wrapping Threadpool public class ThreadPoolWrapper { public static void QueueUserWorkItem(WaitCallback callback) { ThreadPool.QueueUserWorkItem(callback); } }
  • 30. Wrapping Threadpool public class ClassWithWrappedThreadpool { public void RunInThread() { ThreadPool.QueueUserWorkItem(_ => { SomethingImportantHappened = true; }); } public bool SomethingImportantHappened { get; private set; } } ThreadPoolWrapper.QueueUserWorkItem(_ =>
  • 31. Testing with new ThreadpoolWrapper [TestClass] public class WorkingWithThreadpool { [TestMethod, Isolated] public void UsingWrapperTest() { Isolate.WhenCalled(() => ThreadPoolWrapper.QueueUserWorkItem(null)) .DoInstead(ctx => ((WaitCallback)ctx.Parameters[0]).Invoke(null)); var cut = new ClassWithWrappedThreadpool(); cut.RunInThread(); Assert.IsTrue(cut.SomethingImportantHappened); } }
  • 32. How can we test that an asynchronous operation never happens?
  • 33. Test Code Under Test Is Test Async Deterministic Assert Results Run in sync
  • 34. Another day – another class to test public void Start() { _cancellationTokenSource = new CancellationTokenSource(); Task.Run(() => { var message = _messageBus.GetNextMessage(); if(message == null) return; // Do work if (OnNewMessage != null) { OnNewMessage(this, EventArgs.Empty); } }, _cancellationTokenSource.Token); }
  • 35. Switching code to “test mode” • Dependency injection • Preprocessor directives • Pass delegate • Other
  • 36. Run in single thread patterns • Fake & Sync • Async code  sync test
  • 37. Synchronized run patterns When you have to run a concurrent test in a predictable way
  • 38. The Signaled pattern Start Run Code under test Signal Fake object Call Wait Assert result
  • 39. Using the Signaled pattern public void DiffcultCalcAsync(int a, int b) { Task.Run(() => { Result = a + b; _otherClass.DoSomething(Result); }); }
  • 40. Using the Signaled pattern [TestMethod] public void TestUsingSignal() { var waitHandle = new ManualResetEventSlim(false); var fakeOtherClass = A.Fake<IOtherClass>(); A.CallTo(() => fakeOtherClass.DoSomething(A<int>._)).Invokes(waitHandle.Set); var cut = new ClassWithAsyncOperation(fakeOtherClass); cut.DiffcultCalcAsync(2, 3); var wasCalled = waitHandle.Wait(10000); Assert.IsTrue(wasCalled, "OtherClass.DoSomething was never called"); Assert.AreEqual(5, cut.Result); }
  • 41. Busy Assert Start Run Code under test Assert or Timeout
  • 42. Busy assertion [TestMethod] public void DifficultCalculationTest() { var cut = new ClassWithAsyncOperation(); cut.RunAsync(2, 3); AssertHelper.BusyAssert(() => cut.Result == 5, 50, 100, "fail!"); }
  • 43. Synchronized test patterns × Harder to investigate failures × Cannot test that a call was not made Test runs for too long but only when it fails  Use if other patterns are not applicable
  • 44. Unit testing for concurrency issues Because concurrency (and async) needs to be tested as well
  • 45. Test for async Start Method under test Fake object wait Assert results
  • 46. Test for Deadlock Start Execute Code under test Thread WWaaitit Assert result Call Thread
  • 47. [TestMethod, Timeout(5000)] public void CheckForDeadlock() { var fakeDependency1 = A.Fake<IDependency>(); var fakeDependency2 = A.Fake<IDependency>(); var waitHandle = new ManualResetEvent(false); var cut = new ClassWithDeadlock(fakeDependency1, fakeDependency2); A.CallTo(() => fakeDependency1.Call()).Invokes(() => waitHandle.WaitOne()); A.CallTo(() => fakeDependency2.Call()).Invokes(() => waitHandle.WaitOne()); var t1 = RunInOtherThread(() => cut.Call1Then2()); var t2 = RunInOtherThread(() => cut.Call2Then1()); waitHandle.Set(); t1.Join(); t2.Join(); } T1 T2 L1 L2
  • 48. Avoid Concurrency Humble object Test before – test after Run in single thread Fake & Sync Async in production - sync in test Synchronize test The Signaled pattern Busy assertion Concurrency tests Test for Deadlock Test for non blocking Concurrent unit testing patterns
  • 49. Conclusion It is possible to test concurrent code Avoid concurrency Run in single thread Synchronize test
  • 50. Dror Helper C: 972.50.7668543 e: drorh@codevalue.net B: blog.drorhelper.com w: www.codevalue.net

Notes de l'éditeur

  1.  applications will increasingly need to be concurrent if they want to fully exploit CPU throughput gains
  2. If it’s unpredictable – how can we test it?
  3. Image by Mark http://upload.wikimedia.org/wikipedia/commons/0/06/Stay_Alive_and_Avoid_Zombies.png
  4. Humble object becomes thin layer Logic is accessible via new object
  5. Message processing example
  6. Message processing example
  7. Message processing example
  8. Message processing example
  9. Some things cannot be tested