Asynchronen 
Code testen 
@ndrssmn 
Andreas Simon
Synchron 
Übertragungszeit 
Wartezeit 
Bearbeitungszeit 
Wartezeit 
Antwortzeit
Asynchron 
Antwortzeit 
Wartezeit
Fehlertoleranz 
Verfügbarkeit 
Parallelisierung 
Performance 
Event-Driven Architecture
Listening 
Callback
Synchronisation 
TIMEOUT
Listening in JUnit 
@Test public void 
should_reply_with_Fibonacci_numbers() throws Exception { 
// Arrange 
NotificationT...
Listening in Mocha 
describe('AMQP Fibonacci service', function() { 
it('calculates fib(' + MIN + ')', function(done) { 
c...
Sampling 
POST localhost/ 
CREATED Location: localhost/30 
GET localhost/30 
NOT FOUND 
GET localhost/30 
NOT FOUND 
GET l...
Sampling in JUnit 
@Test public void 
calculates_fib_30() throws Exception { 
// Act 
connection = POST("http://localhost:...
public class Poller { 
[…] 
public void check(Probe probe) { 
[…] 
while (!probe.isSatisfied()) { 
[…] 
Thread.sleep(pollD...
Sampling in Mocha 
describe('Fibonacci server', function() { 
it('should calculate fib(20)', function(done) { 
var req = h...
Sampling in Mocha 
function pollGET(url, done) { 
http.get(url, function(res) { 
if(200 != res.statusCode) { 
setTimeout(p...
Test the test 
@Test public void 
is_thread_safe() throws Exception { 
latch = startStressing(STRESSING_THREADS, () -> { 
...
Thread-sicher implementieren 
public class NotificationTrace<T> { 
public void append(T message) { 
synchronized (traceLoc...
Aufräumen 
@After 
public void tearDown() throws InterruptedException { 
executorService.shutdownNow(); 
scheduler.shutdow...
Fazit 
Listening vs. Sampling 
Synchronisierungsmechanismen kapseln (und durch Unit-Tests 
validieren) 
Brian Goetz: "Java...
Quagilis 
Andreas Simon 
Lazarettstr. 9 
48147 Münster 
Fon +49 (0) 251 - 590 491 55-0 
Fax +49 (0) 251 - 590 491 55-9 
a....
Asynchronen Code testen
Nächste SlideShare
Wird geladen in …5
×

Asynchronen Code testen

515 Aufrufe

Veröffentlicht am

Viele performante und gut skalierbare Architekturen setzen auf asynchrone Verarbeitung. Das Testen des asynchronen Codes stellt Entwickler allerdings vor neue Herausforderungen. Dieser Vortrag bietet Orientierung für einige typischen Fragestellungen. Am Beispiel von NodeJS und Mocha wird gezeigt, wie das Testen beim Einsatz einer nicht-blockierenden Event Loop funktioniert. Anschließend illustriert der Vortrag, wie asynchroner Code mit JUnit auf der JVM – einer klassischen Multithreading-Plattform – getestet werden kann. Insbesondere wird darauf eingegangen, welche Synchronisationsmechanismen genutzt werden können und wie Race Conditions durch Unit Tests aufgedeckt werden können.

Code unter: https://github.com/andreassimon/talk-asynchronen-code-testen

Veröffentlicht in: Technologie
0 Kommentare
0 Gefällt mir
Statistik
Notizen
  • Als Erste(r) kommentieren

  • Gehören Sie zu den Ersten, denen das gefällt!

Keine Downloads
Aufrufe
Aufrufe insgesamt
515
Auf SlideShare
0
Aus Einbettungen
0
Anzahl an Einbettungen
46
Aktionen
Geteilt
0
Downloads
3
Kommentare
0
Gefällt mir
0
Einbettungen 0
Keine Einbettungen

Keine Notizen für die Folie

Asynchronen Code testen

  1. 1. Asynchronen Code testen @ndrssmn Andreas Simon
  2. 2. Synchron Übertragungszeit Wartezeit Bearbeitungszeit Wartezeit Antwortzeit
  3. 3. Asynchron Antwortzeit Wartezeit
  4. 4. Fehlertoleranz Verfügbarkeit Parallelisierung Performance Event-Driven Architecture
  5. 5. Listening Callback
  6. 6. Synchronisation TIMEOUT
  7. 7. Listening in JUnit @Test public void should_reply_with_Fibonacci_numbers() throws Exception { // Arrange NotificationTrace<Integer> trace = new NotificationTrace<>(TIMEOUT); String replyQueue = channel.queueDeclare().getQueue(); FibonacciCalculator.create(connection.createChannel()); new IntegerConsumer( connection.createChannel(), trace::append) .consumeQueue(replyQueue); // Act publishNumbers(MIN, MAX, replyQueue); // Assert trace.containsNotification(equalTo(FIB_MIN)); trace.containsNotification(equalTo(FIB_MAX)); }
  8. 8. Listening in Mocha describe('AMQP Fibonacci service', function() { it('calculates fib(' + MIN + ')', function(done) { connection.on('ready', function () { connection.queue('my-queue', function(q) { q.subscribe(function (message) { try { // Assert message.data.toString().should.eql(FIB_MIN); done(); } catch(e) { done(e); } }); // Act connection.publish( 'calculate-fibonacci', MIN, { replyTo: 'my-queue'} ); }); }); });
  9. 9. Sampling POST localhost/ CREATED Location: localhost/30 GET localhost/30 NOT FOUND GET localhost/30 NOT FOUND GET localhost/30 OK :: 832040 TIMEOUT
  10. 10. Sampling in JUnit @Test public void calculates_fib_30() throws Exception { // Act connection = POST("http://localhost:3000/", "30"); fibLocation = connection.getHeaderField("Location"); // Assert Probe probe = responseTo( fibLocation, equalTo(Integer.toString(FIB_30)) ); new Poller(TIMEOUT, POLL_DELAY).check(probe); }
  11. 11. public class Poller { […] public void check(Probe probe) { […] while (!probe.isSatisfied()) { […] Thread.sleep(pollDelayMillis); probe.sample(); } } } public interface Probe { void sample(); boolean isSatisfied(); void describeAcceptanceCriteriaTo(Description d); void describeFailureTo(Description d); }
  12. 12. Sampling in Mocha describe('Fibonacci server', function() { it('should calculate fib(20)', function(done) { var req = http.request(POST_fib, function(res) { res.setEncoding('utf8'); res.statusCode.should.eql(201); res.headers.location.should.be.ok; pollGET(res.headers.location, done); }).on('error', done); req.setHeader('Content-Type', 'application/x-www-form- urlencoded;charset=UTF-8'); req.write('n=20n'); req.end(); });
  13. 13. Sampling in Mocha function pollGET(url, done) { http.get(url, function(res) { if(200 != res.statusCode) { setTimeout(pollGET, POLL_DELAY, url, done); } res.on('data', function (chunk) { chunk.toString().should.eql('6765'); done(); }); }).on('error', done); }
  14. 14. Test the test @Test public void is_thread_safe() throws Exception { latch = startStressing(STRESSING_THREADS, () -> { for (int i = 0; i < ITERATIONS; i++) { trace.append("NOT-WANTED"); Thread.sleep(SLEEPTIME); } latch.countDown(); }); scheduler.schedule( () -> trace.append("WANTED"), 100, TimeUnit.MILLISECONDS ); trace.containsNotification(equalTo("WANTED")); latch.await(); assertThat( trace.getAppendCount(), is(equalTo((long) STRESSING_THREADS * ITERATIONS + 1)) ); }
  15. 15. Thread-sicher implementieren public class NotificationTrace<T> { public void append(T message) { synchronized (traceLock) { trace.add(message); traceLock.notifyAll(); } } public void containsNotification(Matcher<? super T> criteria) throws AssertionError, InterruptedException { Timeout timeout = new Timeout(timeoutMs); synchronized (traceLock) { stream = new NotificationStream<>(trace, criteria); while (!stream.hasMatched()) { if (timeout.hasTimedOut()) { throw new AssertionError(); } timeout.waitOn(traceLock); } } }
  16. 16. Aufräumen @After public void tearDown() throws InterruptedException { executorService.shutdownNow(); scheduler.shutdownNow(); }
  17. 17. Fazit Listening vs. Sampling Synchronisierungsmechanismen kapseln (und durch Unit-Tests validieren) Brian Goetz: "Java Concurrency in Practice" Nat Pryce, Steve Freeman: "Growing Object-Oriented Software" https://github.com/andreassimon/talk-asynchronen-code-testen
  18. 18. Quagilis Andreas Simon Lazarettstr. 9 48147 Münster Fon +49 (0) 251 - 590 491 55-0 Fax +49 (0) 251 - 590 491 55-9 a.simon@quagilis.de http://www.quagilis.de Quality in Agile.

×