Download pdf - Asynchronen Code testen

Transcript
Page 1: Asynchronen Code testen

AsynchronenCode testen

@ndrssmnAndreas Simon

Page 2: Asynchronen Code testen

Synchron

Übertragungszeit

War

teze

it

Bearbeitungszeit

War

teze

itAnt

wor

tzei

t

Page 3: Asynchronen Code testen

AsynchronW

arte

zeit

Ant

wor

tzei

t

Page 4: Asynchronen Code testen

FehlertoleranzVerfügbarkeitParallelisierungPerformance

Event-Driven Architecture

Page 5: Asynchronen Code testen

Listening

Callback

Page 6: Asynchronen Code testen
Page 7: Asynchronen Code testen

Synchronisation

TIMEOUT

Page 8: Asynchronen Code testen

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)); }

Page 9: Asynchronen Code testen

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'} ); }); }); });

Page 10: Asynchronen Code testen

Sampling

POST localhost/

CREATED Location: localhost/30

TIMEOUT

GET localhost/30

NOT FOUND

GET localhost/30

NOT FOUND

GET localhost/30

OK :: 832040

Page 11: Asynchronen Code testen

@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); }

Sampling in JUnit

Page 12: Asynchronen Code testen

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);}

Page 13: Asynchronen Code testen

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=20\n'); req.end(); });

Sampling in Mocha

Page 14: Asynchronen Code testen

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);}

Sampling in Mocha

Page 15: Asynchronen Code testen

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)) ); }

Page 16: Asynchronen Code testen

Thread-sicher implementierenpublic 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); } } }

Page 17: Asynchronen Code testen

Aufräumen

@After public void tearDown() throws InterruptedException { executorService.shutdownNow(); scheduler.shutdownNow(); }

Page 18: Asynchronen Code testen

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

Page 19: Asynchronen Code testen

Quality in Agile.

QuagilisAndreas Simon

Lazarettstr. 948147 Münster

Fon +49 (0) 251 - 590 491 55-0Fax +49 (0) 251 - 590 491 55-9

[email protected]://www.quagilis.de


Recommended