Определите, выполняется ли код как часть модульного теста - PullRequest
94 голосов
/ 02 июля 2010

У меня есть тестовый модуль (nUnit). На многих уровнях вниз по стеку вызовов метод завершится ошибкой, если он запущен через модульный тест.

В идеале вы бы использовали что-то вроде насмешки для настройки объекта, от которого зависит этот метод, но это сторонний код, и я не могу сделать это без большой работы.

Я не хочу настраивать nUnit конкретные методы - здесь слишком много уровней и плохой способ выполнения юнит-теста.

Вместо этого я хотел бы добавить что-то вроде этого глубоко в стек вызовов

#IF DEBUG // Unit tests only included in debug build
if (IsRunningInUnitTest)
   {
   // Do some setup to avoid error
   }
#endif

Так есть идеи о том, как написать IsRunningInUnitTest?

P.S. Я полностью осознаю, что это не очень хороший дизайн, но я думаю лучше, чем альтернативы.

Ответы [ 16 ]

1 голос
/ 11 августа 2012

Я был недоволен этой проблемой недавно.Я решил это немного по-другому.Во-первых, я не хотел делать предположение, что инфраструктура nunit никогда не будет загружена вне тестовой среды;Я был особенно обеспокоен разработчиками, запускающими приложение на своих машинах.Так что вместо этого я прошелся по стеку вызовов.Во-вторых, я смог предположить, что тестовый код никогда не будет запускаться на двоичных версиях выпуска, поэтому я убедился, что этот код не существует в системе выпуска.

internal abstract class TestModeDetector
{
    internal abstract bool RunningInUnitTest();

    internal static TestModeDetector GetInstance()
    {
    #if DEBUG
        return new DebugImplementation();
    #else
        return new ReleaseImplementation();
    #endif
    }

    private class ReleaseImplementation : TestModeDetector
    {
        internal override bool RunningInUnitTest()
        {
            return false;
        }
    }

    private class DebugImplementation : TestModeDetector
    {
        private Mode mode_;

        internal override bool RunningInUnitTest()
        {
            if (mode_ == Mode.Unknown)
            {
                mode_ = DetectMode();
            }

            return mode_ == Mode.Test;
        }

        private Mode DetectMode()
        {
            return HasUnitTestInStack(new StackTrace()) ? Mode.Test : Mode.Regular;
        }

        private static bool HasUnitTestInStack(StackTrace callStack)
        {
            return GetStackFrames(callStack).SelectMany(stackFrame => stackFrame.GetMethod().GetCustomAttributes(false)).Any(NunitAttribute);
        }

        private static IEnumerable<StackFrame> GetStackFrames(StackTrace callStack)
        {
            return callStack.GetFrames() ?? new StackFrame[0];
        }

        private static bool NunitAttribute(object attr)
        {
            var type = attr.GetType();
            if (type.FullName != null)
            {
                return type.FullName.StartsWith("nunit.framework", StringComparison.OrdinalIgnoreCase);
            }
            return false;
        }

        private enum Mode
        {
            Unknown,
            Test,
            Regular
        }
0 голосов
/ 06 ноября 2018

Я использовал следующее в VB в своем коде, чтобы проверить, участвуем ли мы в модульном тесте.по сути, я не хотел, чтобы тест открывал Word

    If Not Application.ProductName.ToLower().Contains("test") then
        ' Do something 
    End If
0 голосов
/ 08 июня 2018

Application.Current равен нулю при работе под модулем тестирования. По крайней мере, для моего приложения WPF, использующего MS Unit tester. Это простой тест, если нужно. Кроме того, что-то следует иметь в виду при использовании Application.Current в вашем коде.

0 голосов
/ 21 февраля 2018

Наличие ссылки на nunit framework не означает, что тест на самом деле запущен.Например, в Unity при активации тестов режима воспроизведения ссылки на объекты добавляются в проект.И когда вы запускаете игру, ссылки существуют, поэтому UnitTestDetector не будет работать правильно.

Вместо того, чтобы проверять сборку nunit, мы можем попросить nunit api проверить, выполняется ли тест сейчас или нет.

using NUnit.Framework;

// ...

if (TestContext.CurrentContext != null)
{
    // nunit test detected
    // Do some setup to avoid error
}
0 голосов
/ 23 мая 2017

Учитывая, что ваш код обычно запускается в главном потоке (gui) приложения Windows Form, и вы хотите, чтобы он вел себя по-другому во время работы в тесте, вы можете проверить на

if (SynchronizationContext.Current == null)
{
    // code running in a background thread or from within a unit test
    DoSomething();
}
else
{
    // code running in the main thread or any other thread where
    // a SynchronizationContext has been set with
    // SynchronizationContext.SetSynchronizationContext(synchronizationContext);
    DoSomethingAsync();
}

Я использую этодля кода, который я хочу fire and forgot в графическом приложении, но в модульных тестах мне может понадобиться вычисленный результат для диссертации, и я не хочу связываться с несколькими выполняющимися потоками.

Работает для MSTest.Преимущество в том, что мой код не должен проверять саму среду тестирования, и если мне действительно нужно асинхронное поведение в определенном тесте, я могу установить свой собственный SynchronizationContext.

Имейте в виду, что это ненадежный методна Determine if code is running as part of a unit test в соответствии с запросом OP, так как код может выполняться внутри потока, но для некоторых сценариев это может быть хорошим решением (также: если я уже запущен из фонового потока, возможно, нет необходимости запускать новый).

0 голосов
/ 07 января 2014

Существует также очень простое решение, когда вы тестируете класс ...

Просто укажите классу, который вы тестируете, свойство, подобное этому:

// For testing purposes to avoid running certain code in unit tests.
public bool thisIsUnitTest { get; set; }

Теперь ваш модульный тест может установить для логического значения thisIsUnitTest значение true, поэтому в коде, который вы хотите пропустить, добавьте:

   if (thisIsUnitTest)
   {
       return;
   } 

Это проще и быстрее, чем проверка сборок. Напоминает мне о Ruby On Rails, где вы можете посмотреть, находитесь ли вы в среде TEST.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...