Можно ли пропустить все тесты из определенного класса, как в NUnit
[TestFixture]
[Ignore("Reason")]
public class TestClass {
}
Можно ли пропустить все тесты из определенного класса, как в NUnit
[TestFixture]
[Ignore("Reason")]
public class TestClass {
}
Нет — такой возможности в настоящее время нет,
Один из быстрых способов добиться эффекта в xUnit — закомментировать public
— частные классы не отражаются (очевидно, что таким образом они не будут отображаться в списке пропуска).
Подумайте о том, чтобы зарегистрировать это как проблему на CodePlex, если вы считаете, что потребность в этом достаточно распространена (лично я не могу представить, чтобы за нее проголосовали, поскольку я просто не сталкиваюсь со случаями, когда мне нужно пропустить целый тестовый класс).
ОБНОВЛЕНИЕ: Другой способ - поместить TraitAttribute
в класс, а затем (при условии, что вы используете бегун xunit.console
) отфильтровать его, запустив с /-trait traitName
. (например, вы можете достичь ExplicitAttribute
, некоторых аспектов инфраструктурной техники BDD ожидающих тестов и аналогичной семантики таким образом - конечно, большая проблема в том, что они не отображаются ни в каких отчетах при использовании любого из этих методов фильтрации)
ОБНОВЛЕНИЕ 2: вы можете сделать
const string skip = "Class X disabled";
[Fact(Skip=skip)]
void Test() {}
Затем вы можете перейти на const string skip = null
, чтобы отменить пропуск. (Не)преимущество этого заключается в том, что тест по-прежнему отображается как пропущенный тест в списке тестов, как правило, с указанием причины, указанной в отчете о выполнении теста (вместо того, чтобы сделать его private
, что делает его, вероятно, забытым)
error xUnit1000: Test classes must be public
- person andrei.ciprian; 20.10.2017
Вот мой хак, чтобы избежать ошибки xUnit1000: тестовые классы должны быть общедоступными (проверено на одном факте, я думаю, что теории тоже можно взломать таким образом).
// Uncomment to enable tests
//public class FactSwitch : FactAttribute { } // public! ahh, a bug!
// Uncomment to disable tests
internal class FactSwitch : Attribute { }
public class MyTests
{
[FactSwitch]
public void MyTest1()
{
"it".ShouldBe("it");
}
}
(3 года спустя)
При поиске того же решения я обнаружил, что есть лучшие способы сделать то же самое. Перепишем приведенный выше пример так, как предложил Рубен Бартелинк (продолжение его идеи).
public class MyTests
{
//const string SkipOrNot = null; // Run all tests
const string SkipOrNot = "reason"; // Skip all tests
[Fact(Skip = SkipOrNot)]
public void MyTest1()
{
"it".ShouldBe("it");
}
}
Натан Купер предложил хорошее улучшение моей идеи:
public class MyTests
{
// Uncomment to disable tests
//private class FactAttribute : Attribute { }
[Fact]
public void MyTest1()
{
"it".ShouldBe("it");
}
}
Так что мне нравятся обе идеи Рубена и Натана. Есть тонкая разница между использованием Skip=something (Рубен) и отказом от использования Skip вообще. Использование Skip поместит все ваши тесты в зону предупреждения о пропущенных тестах, а FactAttribute : Attribute скроет их.
#define Fact Attribute
более компактно и позволит вам продолжать использовать [Fact]
.
- person Brad Wilson; 19.01.2018
const SkipIt = "reason" // change to null to run
, а затем сделать Fact(Skip=SkipIt)
, чтобы сделать это условным
- person Ruben Bartelink; 26.10.2018
private class FactAttribute : Attribute { }
внутри класса, чтобы превзойти [Fact]
, потому что пространства имен.
- person Nathan Cooper; 13.11.2019
Добавление причины почти через год после первоначального вопроса. У меня есть набор тестов, которые вызывают API реального сервера, и я хотел бы запускать их по требованию. С nUnit у него есть атрибут Ignore: с этим набором средство запуска тестов пропустит эти тесты, но я все равно могу запустить его вручную.
xUnit не имеет такой функции. Ближайший из них устанавливает такой атрибут уровня класса и комментирует его, когда я хочу его запустить.
Вы можете добиться этого с помощью специальной команды ITestClassCommand.
См. http://mariangemarcano.blogspot.be/2010/12/xunitnet-running-tests-testcategory.html
Вот еще один хак, который требует минимальных изменений в коде
using FactAttribute = System.Runtime.CompilerServices.CompilerGeneratedAttribute;
using TheoryAttribute = System.Runtime.CompilerServices.CompilerGeneratedAttribute;
Для замены можно использовать любой совместимый атрибут.
Если вы также используете InlineDataAttribute
, вам нужно будет определить замену, поскольку я не думаю, что существует существующий совместимый атрибут.
using InlineDataAttribute = DummyDataAttribute;
[AttributeUsage(AttributeTargets.Method, AllowMultiple = true)]
internal class DummyDataAttribute : Attribute
{
public DummyDataAttribute(params object[] data)
{
}
}
Вы можете создать LocalOnlyFactAttribute
public class LocalOnlyFactAttribute : FactAttribute
{
//uncomment to run on local
//const string skip = null;
//keep this to avoid slow running tests on other env
const string skip = "Disabled slow running tests.";
public override string Skip { get => skip; set => base.Skip = value; }
}
Насколько я знаю, самый простой способ динамически пропустить весь тестовый класс xUnit во время выполнения — это использовать TestFrameworkAttribute
на уровне сборки, чтобы указать на класс, который реализует интерфейс ITestFramework
(или наследуется от XunitTestFramework
, что проще) и который переопределяет метод CreateDiscoverer()
для возврата другого класса, который реализует интерфейс ITestFrameworkDiscoverer
(или наследуется от XunitTestFrameworkDiscoverer
, что проще), где вы, наконец, можете переопределить метод IsValidTestClass()
, чтобы решить, следует ли пропускать класс или нет.
Вот пример кода:
[assembly: TestFramework("MyNamespace.Xunit.MyTestFramework", "MyAssembly")]
namespace MyNamespace.Xunit
{
public class MyTestFramework : XunitTestFramework
{
public MyTestFramework(IMessageSink messageSink)
: base(messageSink)
{
}
protected override ITestFrameworkDiscoverer CreateDiscoverer(
IAssemblyInfo assemblyInfo)
=> new MyTestFrameworkDiscoverer(
assemblyInfo,
SourceInformationProvider,
DiagnosticMessageSink);
}
public class MyTestFrameworkDiscoverer : XunitTestFrameworkDiscoverer
{
public MyTestFrameworkDiscoverer(
IAssemblyInfo assemblyInfo,
ISourceInformationProvider sourceProvider,
IMessageSink diagnosticMessageSink,
IXunitTestCollectionFactory collectionFactory = null)
: base(
assemblyInfo,
sourceProvider,
diagnosticMessageSink,
collectionFactory)
{
}
protected override bool IsValidTestClass(ITypeInfo type)
=> base.IsValidTestClass(type) &&
FilterType(type);
protected virtual bool FilterType(ITypeInfo type)
{
// Insert your custom filter conditions here.
return true;
}
}
}
Протестировано с помощью xUnit 2.4.1
.
Мы используем его в Pomelo.EntityFrameworkCore.MySql (см. -L20" rel="nofollow noreferrer">AssemblyInfo.cs и MySqlXunitTestFrameworkDiscoverer.cs) (немного сложнее, чем пример кода здесь).
Я нашел еще один способ временного отключения всего класса без предупреждения компилятора.
Неполноценный:
[System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "xUnit1000:Test classes must be public", Justification = "Disabled")]//*/
/*
public /**/class DatabaseTests
{
}
чтобы включить перемещение /*
на одну строку вверх (т.е. с помощью alt+up):
/*
[System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "xUnit1000:Test classes must be public", Justification = "Disabled")]//*/
public /**/class DatabaseTests
{
}
Обратите внимание, что использование полного пути к пространству имен для SupressMessage не мешает вашему использованию.
Рассмотрите возможность создания LocalOnlyFactAttribute, который можно повторно использовать в нескольких тестовых файлах.
public class LocalOnlyFactAttribute : FactAttribute
{
//uncomment to run on local
//const string skip = null;
//keep this to avoid slow running tests on other env
const string skip = "Disabled slow running tests.";
public override string Skip { get => skip; set => this.Skip = value; }
}
Вам нужно установить уровень доступа вашего класса как внутренний и подавить сообщение, как это сделал @Miq:
[System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "xUnit1000:Test classes must be public", Justification = "Disabled")]
internal class MyClassThatIsNotATestClass
{ ... }