是否可以将 xUnit 与 LINQPad 一起使用?

kim*_*gro 4 xunit xunit.net linqpad

是否可以将 xUnit 与 LINQPad 一起使用?

能够首先为在 LINQPad 中设计的概念编写一些测试会很棒。这比添加另一个 ConsoleApp23423894238 更容易,只是为了能够快速编写一些单元测试。

Mat*_*att 8

是的,可以将 xUnit 与 LinqPad 一起使用。我已经更新了这个答案,为您提供最新信息,但我给出的原始答案也为您提供了一些有关 xUnit 使用的见解和链接,因此我将其保留以供您参考。


更新:最新版本的LinqPad 6(自 V 6.9.x 及更高版本起,请参阅6.9 发行说明部分现在通过新菜单项/内置了 XUnit 支持。这将添加一个查询,其中包含通过 #load 引用的所需样板代码以便您可以立即开始测试事实和理论。您可以按+ +运行示例测试方法。QueryAdd XUnit Test Support
AltShiftT

例如,将以下新理论添加到样板代码中(在 main 方法之后,将其放在private::Tests区域内):

#region private::Tests

[Theory]
[InlineData(1)]  
[InlineData(3, 6)]  
[InlineData(5, 7, 9)]
void OddNumbers(params int[] values)
{
    static bool IsOdd(int value) => value % 2 == 1;
    foreach (var value in values)
    {
        Assert.True(IsOdd(value), $"IsOdd({value}) is false");  
    } 
}

#endregion
Run Code Online (Sandbox Code Playgroud)

Alt+ Shift+T并检查结果。


动态可跳过的单元测试

您可以修改xunitLinqPad 6 提供的脚本以支持可跳过的单元测试(NUGET 包XUnit.SkippableFact,详细说明参见本答案末尾的“动态跳过测试和理论”链接)。

在 xunit 中进行以下更改:

  1. 函数 RunTests - 添加:runner.OnTestSkipped = info => AddTestResult(info);

  2. 类 TestResultSummary - 添加:public bool Skipped() => _testInfo 是 Xunit.Runners.TestSkippedInfo;

  3. 类 TestResultSummary / 公共对象状态 - 添加:_testInfo 是 Xunit.Runners.TestSkippedInfo 吗?Util.WithStyle ("Skipped", "color:orange") :

这些更改将使xunit脚本能够在结果中显示跳过测试的时间。

要测试它,请XUnit.SkippableFact通过 F4加载 NUGET 包,然后添加测试框架,最后添加测试:

[SkippableFact]
void Test_Xunit3()
{

Skip.If(true, "skipping");

Assert.True(1 + 1 == 2);

}

[SkippableTheory]
[InlineData(1)]
[InlineData(2)]
void Test_Xunit4(int x)
{

Skip.If(x==2, "skipping");

Assert.True(1 + 1 == 2);

}
Run Code Online (Sandbox Code Playgroud)

注意:这些更改也适用于普通的 XUnit。因此,将更改添加到代码中并没有什么坏处。


现在,如果您愿意,请继续阅读原始答案(最后附有一些有用的提示):


两个答案为我指明了正确的方向,但描述还不够完整,所以我不得不尝试一下。为了节省你的时间,我正在描述我所做的;我现在有适用于LinqPad 5 和 LinqPad 6 的工作解决方案

LinqPad 5 - 用于 .NET

根据 Tom 所写的内容,我能够在LinqPad 5 (v5.42.01) 上使用它。

还需要一些更多步骤,这些步骤并不明显,也未在接受的答案中解释,因此我将描述对我有帮助的内容。

首先,您需要使用 LinqPad 的付费版本,因为只有这样您才能加载 NUGET 包。

要在 LinqPad 中加载所需的包,请按F4。查询属性对话框打开。在该对话框中,单击Add NUGET...

NUGET 对话框打开。在 NUGET 对话框的中间,有一个搜索文本框。搜索xUnit.Net- 一旦它显示出来,单击Add to query,等待它加载,然后单击添加命名空间。然后对Xunit.Runner.LinqPad.

然后关闭 NUGET 对话框,但保持查询属性打开。您需要到高级选项卡:启用(勾选)“将所有非框架引用复制到单个本地文件夹。” 现在您可以关闭查询属性对话框。

将以下示例导入查询编辑器(C# Program模式):

void Main()
{
     // Press F4, go to Advanced, then 
     // tick-mark "Copy all non-framework references to a single local folder"
     var me = Assembly.GetExecutingAssembly();
     var result = Xunit.Runner.LinqPad.XunitRunner.Run(me); 
     result.Dump("Xunit runner result");
}
    
/// <summary>
/// This test class is there for demo purpose, so developers can
/// see how to write test methods. 
/// It also verifies that XUnit itself is functioning correctly.
/// </summary>
public class A_XUnitSelfTest
{

    [InlineData(2)]
    [InlineData(3)]
    [Theory]
    public void Test_Theory(int a)
    {
        Assert.True(a == 2 || a == 3); // succeeds
    }

    [Fact]
    public void Test_Fact()
    {
        Assert.False(1 == 0); // succeeds
    }

}
Run Code Online (Sandbox Code Playgroud)

运行它,您将看到测试运行器的输出。

运行 3 个测试中的 3 个......
完成:0,003 秒内进行 3 个测试(0 次失败,0 次跳过)

通过将 中的断言更改为 来修改测试以查看测试失败时的Test_Fact()情况Assert.False(1 == 1);,然后再次运行它。这次应该显示:

运行 3 个测试中的 3 个...
[失败] UserQuery+A_XUnitSelfTest.Test_Fact:Assert.False()
预期失败 :False
实际:
Xunit.Assert.False(Nullable`1 条件,字符串 userMessage)
处 Xunit.Assert.False 处为 True (布尔条件)
在 C:\Users...\AppData\Local\Temp\LINQPad5_oyxxqxbu\query_mxsmky.cs:line 62 中的 UserQuery.A_XUnitSelfTest.Test_Fact()
完成:0,005 秒内进行 3 次测试(1 次失败,0 次跳过)


LinqPad 6 - 用于 .NET Core

LinqPad 6 不同,因为它基于 .NET Core,因此需要不同的库。

从这个开始:

void Main()
{
     // Press F4, go to Advanced, then 
     // tick-mark "Copy all non-framework references to a single local folder"
     var me = Assembly.GetExecutingAssembly();
     var result = Xunit.Runner.LinqPad.XunitRunner.Run(me); 
     result.Dump("Xunit runner result");
}
    
/// <summary>
/// This test class is there for demo purpose, so developers can
/// see how to write test methods. 
/// It also verifies that XUnit itself is functioning correctly.
/// </summary>
public class A_XUnitSelfTest
{

    [InlineData(2)]
    [InlineData(3)]
    [Theory]
    public void Test_Theory(int a)
    {
        Assert.True(a == 2 || a == 3); // succeeds
    }

    [Fact]
    public void Test_Fact()
    {
        Assert.False(1 == 0); // succeeds
    }

}
Run Code Online (Sandbox Code Playgroud)

然后通过对话框添加xUnit.net, xUnit.net [Core Unit Testing Framework]andxUnit.net [Runner Utility]以及它们的所有命名空间F4(详细信息参见 LinqPad 5 会话),最后将@ramiroalvarez 提到的 XUnit 运行器源代码复制到上面 xUnit 测试示例的末尾:

XUnit 运行程序源代码

在 F4 对话框的“高级”选项卡中启用“将所有 nuget 程序集复制到单个本地文件夹”……这应该就足够了,但还没有继续阅读:

如果您尝试它,它会在源代码中抛出异常 InvalidOperationException("请为非框架引用启用影子文件夹选项 (F4 -> 高级)。")。

现在我查看了XUnit runner,发现如果你注释掉 2 行代码,那么它运行良好:

原始代码(位于方法中GetTargetAssemblyFilename):

if (shadowFolder != xunitFolder 
    || Directory.GetFiles(shadowFolder, "xunit.execution.*.dll").Length == 0)
{
    throw new InvalidOperationException("Please enable the shadow folder option ...");
}

// ...

var targetAssembly = Path.Combine(shadowFolder, Path.GetFileName(assemblyFilename));
//Console.WriteLine($"Copy \"{ assemblyFilename }\" -> \"{ targetAssembly }\"");
File.Copy(assemblyFilename, targetAssembly, true);
Run Code Online (Sandbox Code Playgroud)

注释行

// ...
// throw new InvalidOperationException("Please enable the shadow folder option ...");
// ...
// File.Copy(assemblyFilename, targetAssembly, true);
Run Code Online (Sandbox Code Playgroud)

你就完成了!(用v6.8.3版LinqPad 6、X64版测试)


提示:

提示 1:
您可以按照描述将 xUnit 运行程序附加到您的代码中,但在 LinqPad 6 中有一种更优雅的方法:使用文件名将仅包含 xUnit.Runner 源代码的副本保存在与单元测试文件相同的路径中xUnit.Runner.LinqPad6.linq. 然后,将以下内容添加到测试代码的顶部:
LinqPadRunner

现在你已经清理了你的代码!每次创建新测试时,只需记住添加#load命令即可。

提示 2:
为了能够静态跳过事实,将以下 2 个属性添加到测试运行器的代码中:

/// <summary>
/// Skip a Fact (you can override it by setting OverrideSkip=true)
/// </summary>
public class SkipFactAttribute : FactAttribute
{
    /// <summary>
    /// Override SkipFact: Set OverrideSkip=true to run even skipped tests
    /// </summary>
    public static bool OverrideSkip = false; // set to true to ignore skip

    /// <summary>
    /// Constructor. Used to set skip condition.
    /// </summary>
    public SkipFactAttribute()
    {
        if (!OverrideSkip) Skip = "Skipped Fact";
    }
}

/// <summary>
/// Skip a Theory (you can override it by setting OverrideSkip=true)
/// </summary>
public class SkipTheoryAttribute : TheoryAttribute
{
    /// <summary>
    /// Override SkipTheory: Set OverrideSkip=true to run even skipped tests
    /// </summary>
    public static bool OverrideSkip = false; // set to true to ignore skip

    /// <summary>
    /// Constructor. Used to set skip condition.
    /// </summary>
    public SkipTheoryAttribute()
    {
        if (!OverrideSkip) Skip = "Skipped Theory";
    }
}
Run Code Online (Sandbox Code Playgroud)

如果您想跳过测试,这很有用。要跳过测试,只需更换[Fact][SkipFact][Theory]通过[SkipTheory]

如果您正忙于编写测试并且只想测试该单个测试,请将所有属性设置为[SkipFact][SkipTheory]类似,除了您正在编写的单个测试。

然后,为了不时地再次快速运行所有测试 - 无需更改每个属性 - 将以下内容添加到测试套件的初始化部分(请参阅启动和拆卸的全局设置):

public class TestsFixture : IDisposable
{

    public TestsFixture() // running once before the tests
    {
        // true: Ignore Skip and run all tests, false: Skip is effective
        SkipFactAttribute.OverrideSkip = true;
        SkipTheoryAttribute.OverrideSkip = true;
    }

    public void Dispose() // running once, after the tests
    {
         // teardown code
    }
}
Run Code Online (Sandbox Code Playgroud)

如果完成,请恢复[Fact]/[Theory]属性并将.OverrideSkip变量设置回false.

注意:如果您想根据运行时条件跳过事实请查看动态跳过测试和理论


更多关于单元测试

有关使用 xUnit 进行单元测试的一些高级主题,我建议阅读:

如果你想在 Visual Studio 中使用它,你可以在这里找到信息。


Tom*_*get 4

可能的?有点。

这既不是 LINQPad 的主要用例,也不是单元测试的主要用例。

关于 LINQPad,您可以使用现有的测试运行程序,但可能唯一可以与 LINQPad 集成的是控制台运行程序。测试运行程序不是一个简单的程序。尝试Xunit.Runner.LinqPad

至于需要“为正在设计的概念编写一些测试”,请考虑,如果您发现单元测试工作流程不足以创建项目并将其保留在源代码控制中,那么您可能无法从单元测试工作流程中获得足够的价值。获得更多价值的一种方法是使用行为驱动开发(BDD),如果您想用业务可读的语言编写需求,请尝试像 SpecFlow 这样的语言。