TL; DR,这样的问题:差异代码执行时扩展方法存在但未称为
可以扩展方法的存在具有在.NET上的代码的执行什么样的影响(例如JIT /优化)?
背景
我遇到的MSTest的测试失败取决于一个看似不相关的组件是否也进行测试。
我注意到测试失败,并意外地注意到,如果另一个测试程序集加载失败只发生。在Unittests和Integration测试程序集上运行mstest将开始执行集成测试,并在4.5 CLR下的第21次集成测试中失败,但这不会在4.0 CLR下发生(否则为相同的配置)。 我删除了集成测试程序集中的所有测试,但未通过测试。在两个测试程序集都加载的情况下,执行现在看起来像这样,mstest加载这两个程序集,然后在集成测试程序集中执行单个测试,该测试失败。
> mstest.exe /testcontainer:Unittests.dll /testcontainer:IntegrationTests.dll
Loading C:\Proj\Tests\bin\x86\Release\Unittests.dll...
Loading C:\Proj\Tests\bin\x86\Release\Integrationtests.dll...
Starting execution...
Results Top Level Tests
------- ---------------
Failed Proj.IntegrationTest.IntegrationTest21
没有Unittests程序集在执行中,测试通过。
> mstest.exe /testcontainer:IntegrationTests.dll
Loading C:\Proj\Tests\bin\x86\Release\Integrationtests.dll...
Starting execution...
Results Top Level Tests
------- ---------------
Passed Proj.IntegrationTest.IntegrationTest21
我想这一定是在单元测试的dll正在执行的[AssemblyInitialize]
东西,或者也许是某种在Unittest.dll或公共依赖静态的加载测试组件时被修改。我在Unittests.dll中找不到任何静态构造函数或组装体init。我怀疑包含Unittests程序集时的部署差异(以不同版本部署的相关程序集等),但我比较了通过/失败的部署目录,并且它们是二进制等价的。
那么Unittests组件的哪一部分导致测试差异? 从单元测试中,我一次删除了一半的测试,直到我将它深入到单元测试程序集中的源文件。除测试类外,还声明了扩展方法:
除了此扩展类,Unittest程序集现在包含虚拟测试类中的单个测试用例。只有在声明了扩展方法的虚拟测试方法和时才会发生测试失败。直到单元测试DLL是单个文件我可以去掉所有剩余的测试逻辑的,含有该:
// DummyTest.cs in Unittests.dll
[TestClass]
public class DummyTest
{
[TestMethod]
public void TestNothing()
{
}
}
public static class IEnumerableExtension
{
public static IEnumerable<T> SymmetricDifference<T>(
this IEnumerable<T> @this,
IEnumerable<T> that)
{
return @this.Except(that).Concat(that.Except(@this));
}
}
如果任一试验方法或扩展类被移除时,测试通过。两者都存在,测试失败。
在集成测试执行之前(据我所知),没有调用任何一个程序集制作的扩展方法,也没有在Unittests程序集中执行代码。
我确定集成测试足够复杂,以至于JIT在优化方面的差异可能会导致不同,例如在浮点。那是我所看到的吗?
我不会说扩展类导致任何问题。它最终是语法糖,在编译时被替换:'var1.SymmetricDifference(var2)'被替换为'IEnumerableExtension.SymmetricDifference(var1,var2)'。 –
什么是确切的错误信息或异常?事件日志中是否有任何内容?如果您在测试中做了断言,那么报告失败的测试的实际代码是什么。 – CodeCowboyOrg
事件日志中没有任何内容,唯一的例外是AssertFailed,它来自测试中浮点结果的比较。我无法制造出这个问题的最小代价。 –