Кто-нибудь получил совет или знает какие-либо рамки для модульного тестирования многопоточных приложений?
Модульное тестирование многопоточных приложений
Ответы (4)
Попробуйте многопоточныйTC
http://code.google.com/p/multithreadedtc-junit4/
http://code.google.com/p/multithreadedtc-junit4/
Не тестируйте многопоточные приложения. Рефакторинг кода для устранения связи между работой, выполняемой в разных потоках. Затем протестируйте его отдельно.
Обычно вы не проводите модульное тестирование параллелизма многопоточных приложений, поскольку модульные тесты ненадежны и не воспроизводимы — из-за характера ошибок параллелизма обычно невозможно написать модульные тесты, которые последовательно либо терпят неудачу, либо успешны, и поэтому модульные тесты параллельного кода обычно не делают очень полезных модульных тестов.
Вместо этого вы выполняете модульное тестирование каждого отдельного многопоточного компонента вашего приложения в обычном режиме и полагаетесь на сеансы нагрузочного тестирования для выявления проблем параллелизма.
Тем не менее, существуют некоторые экспериментальные среды нагрузочного тестирования для тестирования параллельных приложений, такие как Microsoft CHESS - CHESS многократно запускает заданный модульный тест и систематически исследует все возможные чередования параллельного теста. Это делает ваши модульные тесты надежными и воспроизводимыми.
Однако на данный момент CHESS все еще является экспериментальным (и, вероятно, не может использоваться с JVM) - пока придерживайтесь нагрузочного тестирования, чтобы отсеять проблемы параллелизма.
В тестировании многопоточного кода нет ничего плохого, особенно если многопоточность — это главная роль тестируемого кода. Общий подход к тестированию многопоточного/асинхронного кода состоит в том, чтобы заблокировать основной тестовый поток, перехватить все ошибочные утверждения из других потоков, разблокировать основной тестовый поток и повторно вызвать любые сбои. ConcurrentUnit позаботится обо всем этом за вас:
final Waiter waiter = new Waiter();
new Thread(() -> {
doSomeWork();
waiter.assertTrue(true);
waiter.resume();
}).start();
// Wait for resume() to be called
waiter.await(1000);