是的,可以将 xUnit 与 LinqPad 一起使用。我已经更新了这个答案来给你最新的信息,但是我给你的原始答案也给了你一些关于 xUnit 使用的见解和链接,所以我保留它供你参考。
更新: LinqPad 6 或 7 的最新版本(自 V 6.9.x 及更高版本,请参阅 6.9 Release Notes section) 现在具有内置 XUnit 支持 通过新菜单项Query / Add XUnit Test Support。这将添加一个带有所需样板代码referenced via #load 的查询,以便您可以立即开始测试事实和理论。
您可以通过按 Alt+Shift+T 来运行示例测试方法。
例如,在样板代码中添加以下新理论(就在 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
按 Alt+Shift+T 运行所有测试并检查结果。
注意:它还会在您第一次添加 XUnit 测试支持时向您的查询目录添加一个文件 XUnit.linq - 这是一个支持 xUnit 测试的迷你库,您不应该触摸它 除非您确切地知道自己在做什么。例如,您可以修改此文件以更改测试摘要的显示方式(例如,您可以将参数 Func<UserQuery.TestResultSummary, bool> filter = null 添加到方法 RunTests 并在查询中添加 .Where(filter) 如果过滤器不为空。这允许您可以过滤测试摘要的结果)。
例如:RunTests(filter: f => f.MethodName.StartsWith("Unit")); 只会在摘要中显示名称以“Unit”开头的测试。
动态可跳过的单元测试
您可以修改 LinqPad 6 提供的xunit 脚本以支持可跳过的单元测试(NUGET 包XUnit.SkippableFact,详细说明请参阅此答案末尾的“动态跳过测试和理论”链接)。
在 xunit 中进行以下更改:
-
函数 RunTests - 添加:
runner.OnTestSkipped = info => AddTestResult(info);
-
类 TestResultSummary - 添加:
public bool Skipped() => _testInfo 是 Xunit.Runners.TestSkippedInfo;
-
类 TestResultSummary / 公共对象状态 - 添加:
_testInfo 是 Xunit.Runners.TestSkippedInfo 吗? Util.WithStyle(“跳过”,“颜色:橙色”):
这些更改将使xunit 脚本能够在结果中显示何时跳过测试。
要测试它,通过F4加载NUGET包XUnit.SkippableFact,然后添加测试框架,最后添加测试:
[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);
}
注意:这些更改也适用于普通的 XUnit。所以添加对代码的更改并没有什么坏处。
现在,如果您愿意,请继续阅读原始答案(末尾有一些有用的提示):
两个答案为我指明了正确的方向,但描述还不够完整,所以我不得不尝试一下。为了节省您的时间,我正在描述我的所作所为;我现在有适用于 LinqPad 5 和 LinqPad 6(和 7)的解决方案。
LinqPad 5 - 用于 .NET
根据 Tom 写的内容,我能够让它与 LinqPad 5 (v5.42.01) 一起使用。
还需要一些额外的步骤,这些步骤并不明显,也没有在接受的答案中解释,所以我将描述对我有帮助的步骤。
首先,您需要使用 LinqPad 的付费版本,因为只有这样您才能加载 NUGET 包。
要在 LinqPad 中加载所需的包,请按 F4。查询属性对话框打开。在该对话框中,单击 添加 NUGET...。
NUGET 对话框打开。在 NUGET 对话框的中间,有一个搜索文本框。搜索xUnit.Net - 显示后,单击添加到查询,等到它加载完毕,然后单击添加命名空间。然后对Xunit.Runner.LinqPad.执行相同操作
然后关闭 NUGET 对话框,但保持 查询属性 打开。您需要到 Advanced 标签:启用(勾选)“将所有非框架引用复制到单个本地文件夹。” 现在您可以关闭 查询属性对话框。
将以下示例导入查询编辑器(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
}
}
运行它,您将看到测试运行器的输出。
运行 3 个测试中的 3 个...
已完成:0,003 秒内 3 次测试(0 次失败,0 次跳过)
通过将Test_Fact() 中的断言更改为Assert.False(1 == 1); 来修改测试以查看测试失败的情况,然后再次运行它。这次应该会显示:
运行 3 个测试中的 3 个...
[失败] UserQuery+A_XUnitSelfTest.Test_Fact: Assert.False() 失败
预期:错误
实际:真实
在 Xunit.Assert.False(Nullable`1 条件,字符串 userMessage)
在 Xunit.Assert.False(布尔条件)
在 C:\Users...\AppData\Local\Temp\LINQPad5_oyxxqxbu\query_mxsmky.cs: 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
}
}
然后通过F4对话框添加xUnit.net、xUnit.net [Core Unit Testing Framework]和xUnit.net [Runner Utility]及其所有命名空间(详情见LinqPad 5会话),最后将XUnit runner源代码as mentioned by @ramiroalvarez复制到上面的xUnit测试示例结束:
XUnit runner source code
在 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);
注释行
// ...
// throw new InvalidOperationException("Please enable the shadow folder option ...");
// ...
// File.Copy(assemblyFilename, targetAssembly, true);
你就完成了! (测试用V6.8.3版本的LinqPad 6,X64版本)
提示:
提示 1:
您可以按照描述将 xUnit 运行器附加到您的代码中,但在 LinqPad 6 中有一种更优雅的方式:
将仅包含 xUnit.Runner 源代码的副本保存在与单元测试文件相同的路径中,文件名为 xUnit.Runner.LinqPad6.linq。
然后,将以下内容添加到测试代码的顶部:
现在你已经清理了你的代码!每次创建新测试时,只需记住添加#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";
}
}
如果您想跳过测试,这很有用。要跳过测试,只需将 [Fact] 替换为 [SkipFact] 或将 [Theory] 替换为 [SkipTheory]。
如果您正忙于编写测试并且只想测试单个测试,请将所有属性设置为 [SkipFact] 或同样设置为 [SkipTheory],除了您正在编写的单个测试。
然后,为了不时再次快速运行所有测试 - 无需更改每个属性 - 将以下内容添加到测试套件的初始化部分(请参阅 global setup for startup and teardown):
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
}
}
如果完成,请恢复 [Fact]/[Theory] 属性并将 .OverrideSkip 变量设置回 false。
注意:如果您想跳过基于运行时条件的事实,请查看dynamically skipping test and theory。
更多关于单元测试
有关使用 xUnit 进行单元测试的一些高级主题,我建议阅读:
如果你想在 Visual Studio 中使用它,你可以找到 infos here。