TL;DR,问题:
.NET 中扩展方法的存在对代码的执行有什么影响(例如 JIT/优化)?
背景
我在 MSTest 中遇到测试失败,这取决于是否也测试了看似无关的程序集。
我注意到测试失败,并且偶然注意到只有在加载另一个测试程序集时才会发生失败。在单元测试和集成测试程序集上运行 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
我认为它一定是在 UnitTests dll 上执行的 [AssemblyInitialize] 东西,或者可能是 Unittest.dll 中的某种静态状态或测试程序集时修改的公共(public)依赖项被加载。我在 Unittests.dll 中找不到任何静态构造函数和程序集初始化。我怀疑包含 Unittests 程序集时存在部署差异(依赖程序集部署在不同版本等),但我比较了通过/失败的部署目录,它们是二进制等效的。
那么 Unittests 程序集的哪一部分导致了测试差异? 从单元测试中,我一次删除了一半的测试,直到我将其深入到单元测试程序集中的源文件。与测试类一起,声明了一个扩展方法:
除了这个扩展类之外,Unittest 程序集现在包含一个虚拟测试类中的单个测试用例。仅当我有一个虚拟测试方法 和 声明的扩展方法时,才会发生测试失败。我可以删除所有剩余的测试逻辑,直到 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 差异可能会导致差异,例如在浮点。这就是我所看到的吗?
最佳答案
可能是由于类型加载错误导致的。
当 CLR 运行时加载类或方法时,它始终会检查这些项目中使用的所有类型。类型/方法是否实际被调用并不重要。重要的是声明的事实。返回到您的示例,扩展方法 SymmetricDifference 声明它使用 System.Core 程序集中的 Except 和 Concat 方法。
从 System.Core 程序集加载 System.Linq.Enumerable 类型时发生错误。
该行为的原因可能各不相同。要采取的第一步是记录您在测试失败时遇到的确切异常。
关于c# - 存在但未调用扩展方法时代码执行的差异,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21825738/
我正在学习如何使用Nokogiri,根据这段代码我遇到了一些问题:require'rubygems'require'mechanize'post_agent=WWW::Mechanize.newpost_page=post_agent.get('http://www.vbulletin.org/forum/showthread.php?t=230708')puts"\nabsolutepathwithtbodygivesnil"putspost_page.parser.xpath('/html/body/div/div/div/div/div/table/tbody/tr/td/div
总的来说,我对ruby还比较陌生,我正在为我正在创建的对象编写一些rspec测试用例。许多测试用例都非常基础,我只是想确保正确填充和返回值。我想知道是否有办法使用循环结构来执行此操作。不必为我要测试的每个方法都设置一个assertEquals。例如:describeitem,"TestingtheItem"doit"willhaveanullvaluetostart"doitem=Item.new#HereIcoulddotheitem.name.shouldbe_nil#thenIcoulddoitem.category.shouldbe_nilendend但我想要一些方法来使用
类classAprivatedeffooputs:fooendpublicdefbarputs:barendprivatedefzimputs:zimendprotecteddefdibputs:dibendendA的实例a=A.new测试a.foorescueputs:faila.barrescueputs:faila.zimrescueputs:faila.dibrescueputs:faila.gazrescueputs:fail测试输出failbarfailfailfail.发送测试[:foo,:bar,:zim,:dib,:gaz].each{|m|a.send(m)resc
我正在尝试设置一个puppet节点,但rubygems似乎不正常。如果我通过它自己的二进制文件(/usr/lib/ruby/gems/1.8/gems/facter-1.5.8/bin/facter)在cli上运行facter,它工作正常,但如果我通过由rubygems(/usr/bin/facter)安装的二进制文件,它抛出:/usr/lib/ruby/1.8/facter/uptime.rb:11:undefinedmethod`get_uptime'forFacter::Util::Uptime:Module(NoMethodError)from/usr/lib/ruby
我在使用omniauth/openid时遇到了一些麻烦。在尝试进行身份验证时,我在日志中发现了这一点:OpenID::FetchingError:Errorfetchinghttps://www.google.com/accounts/o8/.well-known/host-meta?hd=profiles.google.com%2Fmy_username:undefinedmethod`io'fornil:NilClass重要的是undefinedmethodio'fornil:NilClass来自openid/fetchers.rb,在下面的代码片段中:moduleNetclass
对于具有离线功能的智能手机应用程序,我正在为Xml文件创建单向文本同步。我希望我的服务器将增量/差异(例如GNU差异补丁)发送到目标设备。这是计划:Time=0Server:hasversion_1ofXmlfile(~800kiB)Client:hasversion_1ofXmlfile(~800kiB)Time=1Server:hasversion_1andversion_2ofXmlfile(each~800kiB)computesdeltaoftheseversions(=patch)(~10kiB)sendspatchtoClient(~10kiBtransferred)Cl
我想了解Ruby方法methods()是如何工作的。我尝试使用“ruby方法”在Google上搜索,但这不是我需要的。我也看过ruby-doc.org,但我没有找到这种方法。你能详细解释一下它是如何工作的或者给我一个链接吗?更新我用methods()方法做了实验,得到了这样的结果:'labrat'代码classFirstdeffirst_instance_mymethodenddefself.first_class_mymethodendendclassSecond使用类#returnsavailablemethodslistforclassandancestorsputsSeco
我在我的项目中添加了一个系统来重置用户密码并通过电子邮件将密码发送给他,以防他忘记密码。昨天它运行良好(当我实现它时)。当我今天尝试启动服务器时,出现以下错误。=>BootingWEBrick=>Rails3.2.1applicationstartingindevelopmentonhttp://0.0.0.0:3000=>Callwith-dtodetach=>Ctrl-CtoshutdownserverExiting/Users/vinayshenoy/.rvm/gems/ruby-1.9.3-p0/gems/actionmailer-3.2.1/lib/action_mailer
我正在编写一个包含C扩展的gem。通常当我写一个gem时,我会遵循TDD的过程,我会写一个失败的规范,然后处理代码直到它通过,等等......在“ext/mygem/mygem.c”中我的C扩展和在gemspec的“扩展”中配置的有效extconf.rb,如何运行我的规范并仍然加载我的C扩展?当我更改C代码时,我需要采取哪些步骤来重新编译代码?这可能是个愚蠢的问题,但是从我的gem的开发源代码树中输入“bundleinstall”不会构建任何native扩展。当我手动运行rubyext/mygem/extconf.rb时,我确实得到了一个Makefile(在整个项目的根目录中),然后当
设置:狂欢ruby1.9.2高线(1.6.13)描述:我已经相当习惯在其他一些项目中使用highline,但已经有几个月没有使用它了。现在,在Ruby1.9.2上全新安装时,它似乎不允许在同一行回答提示。所以以前我会看到类似的东西:require"highline/import"ask"Whatisyourfavoritecolor?"并得到:Whatisyourfavoritecolor?|现在我看到类似的东西:Whatisyourfavoritecolor?|竖线(|)符号是我的终端光标。知道为什么会发生这种变化吗? 最佳答案