如何根据当前平台跳过xUnit中的特定测试

问题描述 投票:0回答:7
  • 我有一个在 Windows 上构建的程序集
  • 我想在 Linux 中的 mono 上运行 xUnit 测试。

但是,我发现虽然其中 400 个测试可以(按顺序)运行,但某些测试要么挂起 xUnit 运行程序,要么完全关闭它。

我不关心如果某些测试无法在Linux上运行,某些测试与DTC和一些我们不需要在那里支持的非托管guph有关。

然而,我真正想要的是对这些测试应用忽略,并在构建输出中正确标记测试被忽略的事实。

这个问题可以归结为我猜有一些可能的解决方案

  • 如何通过控制台运行程序在 xUnit 中运行特定测试? (我还没有找到这方面的文档,也许我只是不够努力)
  • 是否可以采取其他方式并说“这是一个程序集,但请忽略这些特定测试”
  • 有人提出了一种更好的方法,在这些测试上添加属性,以正式记录这些测试是特定于平台的 - 这可能吗?

如果我可以避免过多修改原始代码,那就太棒了,因为代码并不是我真正可以更改的,并且应用大量跨平台黑客可能不会太顺利。

xunit
7个回答
281
投票

XUnit v2.0 现已推出。它直接支持可跳过的测试。用途:

[Fact (Skip = "specific reason")]

69
投票

我会避免外部化跳过测试(即配置/命令文件,如果可能的话)。这在某种程度上不利于使测试易于运行且值得信赖。当其他人开始参与时,在代码中忽略测试是最安全的方法。

我可以看到很多选项,这里有两个涉及修改现有代码。

选项 1 - 最具侵入性的编译时平台检测

在 VS 解决方案中,定义另一个配置来定义预编译器标志

MONOWIN
(只是为了明确表示它是一个标志,表示它用于在 Windows 上编译以在 Mono 上使用的代码)。

然后定义一个属性,该属性将使测试在为 Mono 编译时被忽略:

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

实际上很难找到这种方法的任何优点,因为它涉及到对原始解决方案的模拟,并添加了另一个需要支持的确认。

选项 2 - 有点侵入性 - 运行时平台检测

这里有一个与选项1类似的解决方案,只不过不需要单独配置:

public class IgnoreOnMonoFactAttribute : FactAttribute {

    public IgnoreOnMonoFactAttribute() {
        if(IsRunningOnMono()) {
            Skip = "Ignored on Mono";
        }
    }
    /// <summary>
    /// Determine if runtime is Mono.
    /// Taken from http://stackoverflow.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

如果某个方法标有

[Fact]

[IgnoreOnMonoFact]
,则 
xUnit 运行程序将运行该方法两次。 (CodeRush 不会这样做,在这种情况下我假设 xUnit 是正确的)。这意味着任何测试方法都必须将
[Fact]
替换为
[IgnoreOnMonoFact]

注2

CodeRush 测试运行程序仍然运行

[IgnoreOnMonoFact]
测试,但它确实忽略了
[Fact(Skip="reason")]
测试。我认为这是由于 CodeRush 反映了 xUnit,而不是在 xUnit 库的帮助下实际运行它。这与 xUnit runner 配合得很好。


69
投票

现在有新选项了。

添加 Nuget 包 SkippableFact,它允许您使用

[SkippableFact]
代替
[Fact]
,并且您可以在测试中使用
Skip.<xyz>
在运行时动态跳过测试。

示例:

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

    // Test Windows only functionality.
}

8
投票

[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,这无疑不是很好。


3
投票

多米尼克的解决方案通过以下代码对我有用:

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

    // Act

    // Assert

}

0
投票

添加到之前有关 SkippableFact 的答案:请注意,每个测试仍然是构造的 - 构造函数正在运行。

如果基类构造函数中有耗时的代码,另一种方法是将特定于环境的测试用例收集在合适的文件中,并在构造函数中运行环境检查:

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

这可以大大加快测试运行速度。在我们的系统中,我们要么扩展“通用”基测试类(在所有环境中运行),要么扩展特定于环境的基测试类。我发现这比管道或其他解决方案中的过滤更容易维护。


-1
投票

这个问题现已在 1.8 中解决 - 您可以根据特征进行过滤。请参阅此问题日志

更新:特征适用于控制台运行程序,但不适用于 MSBuild,我添加了此支持的功能请求。

© www.soinside.com 2019 - 2024. All rights reserved.