тестовые асинхронные задачи - PullRequest
2 голосов
/ 07 декабря 2010

Я ищу общие мысли и / или ссылки по теме в целом, хотя моей конкретной мотивацией на данный момент являются задачи пользовательского интерфейса, связанные с отчетами о ходе работ с использованием BackgroundWorker и / или TPL. Мой опыт работы с асинхронным программированием в целом новичок. Лучшими инструментами тестирования являются NUnit и Rhino.

Некоторые идеи мозгового штурма с моей головы:

  1. Не беспокойтесь - это слишком сложно, и вы просто тестируете BGW или TPL.
  2. Сделай какую-нибудь подделку или издевайся.
  3. Использовать EventWaitHandles

1 Ответ

6 голосов
/ 07 декабря 2010

Модульное тестирование асинхронного кода - не самая простая вещь в мире, как я узнал, когда писал модульные тесты для моей библиотеки Nito.Async .:)

Сначала вы хотите определить, что вы действительно хотите проверить.Вы просто хотите проверить, выполняется ли асинхронное действие, или вы хотите убедиться, что ваши BGW / задачи правильно синхронизируют свои отчеты о ходе выполнения пользовательского интерфейса?

Тестирование действия довольно простое: просто подождите, пока действиезавершено, а затем проверьте наличие постусловий.(Тем не менее, имейте в виду, что BGW RunWorkerCompleted будет вызываться в потоке ThreadPool, если вы не зададите ему контекст синхронизации, как в примере ниже).

Проверка правильности синхронизации (например, для каждого фрагмента кодаработает в правильном потоке) более сложный.

Для каждого теста вам необходимо установить контекст синхронизации.Это будет издеваться над контекстом синхронизации пользовательского интерфейса.Моя библиотека Nito.Async может помочь с этим;он имеет ActionThread, который является отдельным потоком, который содержит контекст синхронизации, подходящий для владения компонентами EAP (например, BGW) и планирования задач (например, TaskScheduler.FromCurrentSynchronizationContext).

Он может использоваться следующим образом (используя пример MSTest):

[TestMethod]
public void Test()
{
  using (ActionThread thread = new ActionThread())
  {
    thread.Start();

    // Anything passed to Do is executed in that ActionThread.
    thread.Do(() =>
    {
      // Create BGW or call TaskScheduler.FromCurrentSynchronizationContext.
    });

    // The thread is gracefully exited at the end of the using block.
  }
}

Я считаю Thread.CurrentThread.ManagedThreadId и Thread.CurrentThread.IsThreadPoolThread самыми простыми способами проверки правильности синхронизации.Если ваш тестовый код запускается из ActionThread.Do, то он должен синхронизировать свои обновления прогресса (и уведомления о завершении) с этим ActionThread.

Во многих модульных тестах Nito.Async используется ActionThread втаким образом, чтобы вы могли искать там различные примеры.

...