Racy Little Number
Na dziś przygotowałem zagadkę skierowaną przede wszystkim dla tych, którzy piszą testy do swojego kodu. Praktykujesz TDD, BDD lub używasz innej techniki – na pewno poradzisz sobie z zagadką.
- Jak często poniższy test się powiedzie?
import junit.framework.TestCase;
public class Test extends TestCase {
int number;
public void test() throws InterruptedException {
number = 0;
Thread t = new Thread(new Runnable() {
public void run() {
assertEquals(2, number);
}
});
number = 1;
t.start();
number++;
t.join();
}
}
Odpowiedzi:
(a) Zawsze się nie powodzi
(b) Czasami się powodzi
(c) Zawsze się powodzi
(d) Zawsze się zawiesza
- Odpowiedź uzasadnij i wyjaśnij dlaczego tak to działa
- Jak poprawić powyższy kod, aby zachowywał się zgodnie z intuicją
Autorami zagadki są Joshua Bloch i William Pugh
Kategorie:Java Puzzle assertEquals, InterruptedException, join, JUnit, Runnable, start, TestCase, Thread
Odpowiedź: test zawsze się powiedzie
Uzasadnienie: wyjątek rzucany przez asercję w ciele wątku roboczego nie zostanie nigdzie przekazany. Wątek roboczy po rzuceniu wyjątku przez asercję po prostu się zakończy nie przekazując żadnej informacji do kontenera testów.
Wersja poprawiona:
import junit.framework.TestCase; public class Test extends TestCase { Error err; Exception e; int number; public void setUp() { err = null; e = null; } public void test() throws InterruptedException { number = 0; Thread t = new Thread(new Runnable() { public void run() { try { assertEquals(2, number); } catch (Error e1) { err = e1; } catch (Exception e1) { e = e1; } } }); number = 1; t.start(); number++; t.join(); } public void tearDown() throws Exception { if (err != null) { throw err; } if (e != null) { throw e; } } }