Pull to refresh

Comments 17

UFO just landed and posted this here
>не является злом и его довольно легко провести
Во-первых, скорее всего у вас в потоках уже есть таймауты (или просто длительная обработка — а иначе и потоки обычно не нужны), и когда вы добавляете еще таймаутов в тестах, будет очень сложно выбрать значения для них. Ложные срабатывания, тесты то зеленые, то красные, в зависимости от погоды.
Во-вторых, это частное решение не решает одну существенную проблему — он не позволяет строить и проверять предположения о том, в каком порядке происходили события в асинхронной системе. И происходили ли вообще. А при тестировании многопоточной системы это может быть довольно важно.

Ну то есть, чуть легче-то будет, да. Но легко не станет нифига.
Ну почему-же — для UI асинхронность очень полезна, причем в сложных случаях именно ручное управление потоками а не асинхронные вызовы: так быстрее и понятнее.

;)
это отсылка к основному правилу радиотехники, озвученному еще в христоматии Хоровица
На самом деле, все что вы описываете — это синхронные процессы) которые выполняются последовательно-параллельно и управляются через семафоры или обратные вызовы или другие механизмы обеспечивающие синхронность) Я просто из другой отрасли) и меня улыбает слушать про асинхронные процессы. То что у вас описано, не в полной мере асинхронный процесс.
Для примера приведу вариант асинхронного процесса в программировании. Представьте, чтоту вас есть функция(поток), которая ищет в некоторой области памяти максимальное значение (в массиве) как только что-то в памяти изменяется, начинает меняться знаяение на выходе функции (в другой области памяти, например, записывается максимум). Вы не можете никак влиять на работу потока, вы только можете знать его архитектуру и максимальное время через которое результат будет достоверен, хотя она может найти результат и раньше. Вопрос, как тестировать эту функцию(поток)?
Как только вы введете семафор который будет запускать поиск или сообщать о завершении поиска, поток станет синхронный.
И да, основное преимущество асинхронных схем — это очень высокая скорость, выше чем у синхронных, но… все равно, избегайте асинхронных схем.

Вы хотите сказать что мои потоки не синхронны а параллельны?
Но позвольте — вот я из графического потока запускаю поток, который ожидает API вызовов от скрипта сам же их и исполняет, максимум как взаимодействует с основным потоком — через механизм отложенных действий просит что-нибудь отрисовать или считать. И такой поток — не один и не забывайте про потоки скриптов. Если потоки не касаются вычислений — они могут быть асинхронными.
Или вы про то что все может быть на одноядерной машине — так любые сущности можно виртуализировать.
Если хотите чтобы я вас понял — приведите определение асинхронного потока.

Наоборот, я хочу сказать, что то, что вы описываете это синхронные процессы, вы их синхронизируете тем или иным образом с основным потоком. Запускаемые вами тесты параллельные, но ни асинхронные, как описано в заголовке статьи.
Если смотреть с точки зрения "основного правила" в статье классический способ избегания асинхронности — синхронизация.
Опредерение асинхронности в программировании: не блокируемость основого потока, но в примере основной поток блокируется и ждет пока все тесты выполнятся.
Если вы что-то запустили и оно выполнилось и сообщило вам — это параллельность, но не асинхронность.
Для примера, еще один вариант классической асинхронности — это нейронная сеть охваченнвя обратной связью, на входе у нее набор данных, как только данные меняются, сеть начинает ее пересчитывать и через некоторое время распространения начнут меняться данные на выходе, но за счет обратной связи вы не знаете, когда завершится изменение данных на выходе и завершиться ли вообще… Это будет пример асинхронного процесса.
Представьте, что у вас есть возможность запустить на GPU N таких сетей и тестировать. Это будет поточное тестирование асинхронных кодов ))))
Ладно, извиняюсь, что глубоко копнул, просто то, что пытаются обычно приподнести в качестве асинхронности, на проверку оказывается синхронным процессом и потоком.
У вас процесс тестирования многопоточный, но синхронный, по моему мнению.

Спасибо, очень интересно (у меня правда не тесты а просто ПО, но все равно) собственно, системные вызовы называются асинхронными — я к тому, что не мы (разрабы) придумали использовать термин асинхронность и тестировать все-равно такие вещи сложно: если потоки основного приложения еще в .NET Framework и могут быть запущены под отладчиком студии, то скрипты-то это отдельные процессы на собственных интерпретаторах.

Почему в последнем примере waiter будет ждать двух вызовов?

пока ждал ответа, почитал официальную документацию.
приведенный пример не правильный. Вот пример из документации, который сработает.


@Test
public void shouldDeliverMessages() throws Throwable {
  final Waiter waiter = new Waiter();

  messageBus.registerHandler(message -> {
    waiter.assertEquals(message, "foo");
    waiter.resume();
  };

  messageBus.send("foo");
  messageBus.send("foo");
  messageBus.send("foo");

  // Wait for resume() to be called 3 times
  waiter.await(1000, 3);
}

дополнено:


А вот пример из оригинальной статьи, токорый тоже будет работать.


Waiter waiter = new Waiter();
messageBus.registerHandler(message -> {
  waiter.resume();
};
messageBus.publish("one");
messageBus.publish("two");
waiter.await(1, TimeUnit.SECONDS, 2);
shalomman, благодарю за разбор! Заменил оригинальный код вашим кодом. Оригинал у автора сегодня также был исправлен.
Я надеялся увидеть как юнит тестом race condition поймать, либо подобное.

Этот Waiter по поведению очень похож на обычное CompletableFuture

Вот как раз то же самое хотел написать. Сам использую CompletableFuture в подобных случаях, при тестировании асинхронного AMQP.

Имхо этот пример из какой то далекой далекой галактики, в реальном приложении реальные обработчики, и никто не будет заменять их тестовыми, ибо становиться непонятно что мы тут тестируем. У реальный обработчиков что то да можно замокать, соответственно можно убедиться что сообщение получено. В случае облаков и(или) хайлодов вы скорее всего используете метрики, и Вам не составит труда вытащить из MeterRegistry значения до и после, ничего не мокая. Но подождать в любом случае прийдеться.
Sign up to leave a comment.

Articles