Как пропустить определенные тесты в 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");
Это может значительно ускорить тестовый прогон. В нашей системе мы либо расширяем «общий» базовый тестовый класс (работает во всех средах), либо специфичный для среды базовый тестовый класс. Я считаю, что это легче поддерживать, чем фильтрацию в конвейерах или других решениях.