Как пропустить определенные тесты в xUnit на основе текущей платформы

  • У меня есть сборка, которую я построил на Windows
  • Я хочу запустить тесты xUnit на моно в Linux.

Тем не менее, я обнаружил, что хотя 400 из этих тестов могут выполняться (по порядку), некоторые тесты либо вешают xUnit, либо полностью его выключают.

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

Однако я хочу применить игнорирование к этим тестам и иметь факт, что тест был проигнорирован правильно в выходных данных сборки.

Вопрос можно свести ко мне, я думаю, ряд возможных решений

  • Как запустить определенные тесты в xUnit через консольный запуск? (Я не нашел документацию для этого, может быть, я просто не выгляжу достаточно усердно)
  • Можно ли пойти другим путем и сказать: "Вот сборка, пожалуйста, игнорируйте эти конкретные тесты, хотя"
  • Наличие атрибута в этих тестах было предложено лучшим способом для официального документирования того, что эти тесты зависят от платформы - возможно ли это?

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

8 ответов

Решение

Я бы избегал внешних тестов пропуска (т. Е. Файл конфигурации / команды, если это возможно). Это несколько противоречит тому, что тесты легко выполнять и заслуживают доверия. Создание тестов, игнорируемых в коде, является самым безопасным подходом, когда другие люди начинают вмешиваться.

Я мог видеть несколько вариантов, вот два, которые включают изменение существующего кода.

Вариант 1. Наиболее навязчивое обнаружение платформы времени компиляции.

В решении VS определите другую конфигурацию, которая определяет флаг прекомпилятора MONOWIN (только для того, чтобы явно указать флаг, он говорит, что он предназначен для кода, скомпилированного в Windows, для использования в Mono).

Затем определите атрибут, который будет игнорировать тест при компиляции для Mono:

public class IgnoreOnMonoFactAttribute : FactAttribute {
#if MONOWIN
    public IgnoreOnMonoFactAttribute() {
        Skip = "Ignored on Mono";
    }
#endif
}

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

Вариант 2 - несколько навязчивый - обнаружение платформы во время выполнения

Вот аналогичное решение для option1, за исключением того, что не требуется отдельной конфигурации:

public class IgnoreOnMonoFactAttribute : FactAttribute {

    public IgnoreOnMonoFactAttribute() {
        if(IsRunningOnMono()) {
            Skip = "Ignored on Mono";
        }
    }
    /// <summary>
    /// Determine if runtime is Mono.
    /// Taken from http://stackru.com/questions/721161
    /// </summary>
    /// <returns>True if being executed in Mono, false otherwise.</returns>
    public static bool IsRunningOnMono() {
        return Type.GetType("Mono.Runtime") != null;
    }
}

Примечание 1

xUnit runner запустит метод дважды, если он помечен [Fact] а также [IgnoreOnMonoFact], (CodeRush не делает этого, в этом случае я предполагаю, что xUnit является правильным). Это означает, что любые методы испытаний должны иметь [Fact] заменено на [IgnoreOnMonoFact]

Заметка 2

Тестер Runner CodeRush все еще управлял [IgnoreOnMonoFact] тест, но он игнорировал [Fact(Skip="reason")] тестовое задание. Я предполагаю, что это связано с тем, что CodeRush отражает xUnit, а не запускает его с помощью библиотек xUnit. Это отлично работает с бегуном xUnit.

XUnit v2.0 теперь доступен. Пропускаемые тесты поддерживаются им напрямую. Использование:

[Fact (Skip = "specific reason")]

Есть новые опции сейчас.

Добавьте пакет Nuget SkippableFact, который позволяет использовать [SkippableFact] вместо [Fact] и вы можете использовать Skip.<xyz> в рамках тестов для динамического пропуска теста во время выполнения.

Пример:

[SkippableFact]
public void SomeTestForWindowsOnly()
{
    Skip.IfNot(Environment.IsWindows);

    // Test Windows only functionality.
}

[Fact(Skip="reason")]

работает, но я предпочитаю использовать черты

      [Fact, Trait("type","unit")]
public void MyUnitTest(){
  // given 
  // when
  // then
}

[Fact, Trait("type","http")]
public void MyHttpIntegrationTest(){
  // given 
  // when do things over HTTP
  // then
}

Применение

      dotnet test --filter type=unit

это защищает наши сборки от случайного запуска интеграционных тестов, которые разработчики забыли пропустить, например [Fact(Skip="Integration")], однако он требует, чтобы модульные тесты «принимали участие» в CI, добавляя правильные черты, что, по общему признанию, не очень хорошо.

Решение Доминика работает для меня по этому коду:

      [SkippableFact]
public void Get_WhenCall_ReturnsString()
{
    // Arrange
    Skip.IfNot(RuntimeInformation.IsOSPlatform(OSPlatform.Windows));

    // Act

    // Assert

}

Это теперь решено в 1.8 - вы можете фильтровать по чертам. Смотрите этот журнал проблем.

Обновление: Черты работают с консольным бегуном, но не с MSBuild, я добавил запрос функции для этой поддержки.

Это было бы идеальным использованием признаков, но, к сожалению, ни командная строка, ни файл проекта xml не поддерживают фильтрацию по признакам. Для этого стоит добавить проблему на сайт Codeplex.

Чтобы добавить к предыдущим ответам относительно SkippableFact: обратите внимание, что каждый из тестов все еще создается - конструктор запускается.

Если у вас есть трудоемкий код в конструкторе базового класса, альтернативой является сбор конкретных тестовых примеров среды в подходящих файлах и запуск проверки среды в конструкторе:

              if (!SupportsTemporalQueries())
            throw new SkipException("This test class only runs in environments support temporal queries");

Это может значительно ускорить тестовый прогон. В нашей системе мы либо расширяем «общий» базовый тестовый класс (работает во всех средах), либо специфичный для среды базовый тестовый класс. Я считаю, что это легче поддерживать, чем фильтрацию в конвейерах или других решениях.

Другие вопросы по тегам