人们将如何去做呢? (代码覆盖率) [英] How would one go about doing this? (Code Coverage)
问题描述
我感兴趣地注意到,似乎缺乏用于.NET测试覆盖率分析的开源工具.我对.NET相当满意,但是我脑中浮躁,我无法弄清楚如果不创建自己的运行时版本或篡改代码编译时发出的IL,别人怎么能做到这一点.听起来像是很棒的简历材料,精神错乱,或者可能两者兼而有之.)
我只是有点好奇,但我不确定这种事情通常是如何完成的.
I''ve noted with interest that there seems to be a lack of open source tools for .NET test coverage analysis. I''m pretty comfortable with .NET, but off the top of my head, I can''t figure out how someone could do it without making their own version of the runtime or tampering with the IL emitted when code is compiled (which sounds like either great resume material, insanity, or possibly both).
I''m just kind of curious, but I''m not sure even how this sort of thing is typically done.
推荐答案
比篡改IL更容易篡改源代码.我曾经做过正式的单元测试,但我不知道这是否是一个正式的术语,但我们称其为插入文件",并且自动化程序是由自动化完成的.我>.诀窍是在不实际更改代码控制流的情况下修改源代码.执行以下功能:
Easier than tampering with the IL is tampering with the source code. I used to do formal unit testing and I don''t know if it''s a formal term or not but we called it "instrumenting a file" and it''s a bit of tedium that automated processes are made for. The trick is to modify the source without actually changing the control flow of the code. Take the following function:
private void MyMethod()<br />{<br /> int x = SomeFunction();<br /> int y = SomeOtherFunction();<br /><br /> if (x > y)<br /> {<br /> // do something<br /> }<br /> else<br /> {<br /> // do something else<br /> }<br />}
您需要确保执行5位代码,因此请在每个位置插入一个布尔值:
There are 5 bits of code you need to ensure are executed, so for each place insert a boolean:
static bool flag1 = false;<br />static bool flag2 = false;<br />static bool flag3 = false;<br />static bool flag4 = false;<br />static bool flag5 = false;<br /><br />private void MyMethod()<br />{<br /> flag1 = true; // verify that the method even gets called<br /><br /> int x = SomeFunction();<br /><br /> flag2 = true; // if SomeFunction() throws an unhandled exception this won''t be executed<br /><br /> int y = SomeOtherFunction();<br /><br /> flag3 = true; // same thing with SomeOtherFunction()<br /><br /> if (x > y)<br /> {<br /> flag4 = true; // verify the true case<br /> // do something<br /> }<br /> else<br /> {<br /> flag5 = true; // verify the false case<br /> // do something else<br /> }<br />}
然后您可以运行测试用例并检查其中的值确保所有代码都已执行.请注意,代码的控制流程没有更改,我们只是添加了一些内容以验证所有位均已执行.当您开始考虑源代码的无穷变化时,就会遇到困难.例如:
Then you can run your test cases and check the value of your bools to make sure that all of your code was executed. Note that the control flow of the code hasn''t changed, we''ve just added stuff to verify that all bits are executed. The difficulty comes in when you start taking into account the endless variations of source code. For example:
private void MyMethod()<br />{<br /> int x = SomeFunction();<br /> int y = SomeOtherFunction();<br /><br /> if (x > y)<br /> {<br /> // do something<br /> }<br />}
看起来更容易,但是当您检测该方法以证明if
语句可能失败时,仍然需要在if
上插入else
.如果if
不能失败,则它是不必要的(死代码),因此不应存在.
要测试(和测试)的最大PITA是完整的MCDC覆盖范围(通过Google搜索).采取以下示例:
looks easier, but you still need to insert the else
to the if
when you instrument that method to prove that the if
statement can be failed. If the if
can''t be failed then it''s unnecessary (dead code) and shouldn''t be there.
The biggest PITA to instrument (and test) is full MCDC coverage (google it). Take the following sample:
private void MyMethod(bool a, bool b)<br />{<br /> if (a || b)<br /> {<br /> // do something<br /> }<br />}
那里有一个多条件的if
语句,您需要证明这两个条件都是必要的.为什么?好吧,假设假设a
始终为true
.然后,该语句将始终求值为true
,并且检查a
或b
没有任何意义.如果b
始终为true,则会发生相同的情况,因此您需要进行检测,以证明a
和b
都可以彼此独立为false
.为了验证完整的覆盖范围,一个语句变成了这样的内容:
There''s a multi-conditional if
statement there, and you need to prove that both conditions are necessary. Why? Well, suppose hypothetically that a
is always true
. Then the statement will always evaluate to true
and there''s no point in checking either a
or b
. The same thing happens if b
is always true, so you need to instrument that in such a way to prove that both a
and b
can be false
independently of each other. To verify full coverage that one statement turns into something like this:
static bool flag1 = false;<br />static bool flag2 = false;<br />static bool flag3 = false;<br />static bool flag4 = false;<br /><br />private void MyMethod(bool a, bool b)<br />{<br /> flag1 = true;<br /><br /> if (a && !b)<br /> {<br /> flag2 = true;<br /> // do something<br /> }<br /> else<br /> {<br /> // a is definitely false <br /> if (b)<br /> {<br /> flag3 = true;<br /> // do something<br /> }<br /> else<br /> {<br /> flag4 = true;<br /> // don''t forget the implicit else<br /> }<br /> }<br />}
,而这仅仅是一个简单的多条件语句!尝试弄清楚如何将其分解:
and that ''s just a simple multi-conditioned statement! Try figuring out how to break this down:
if (a || ((b && c) || d) || (x > 2))<br />{<br /> // we''re all guilty of this at least once :)<br />}
希望您不必在意这些事情,或者您可以负担得起为您执行此操作的工具.相信我,它会使您发疯.
Hopefully you either don''t care about such things or you can afford to buy a tool to do this for you. Trust me, it will drive you crazy.
.NET Framework具有可用于此类的分析API.一个东西.此处是一个很好的介绍文章. [
The .NET Framework has a profiling API available for just such a thing. Here''s a nice introductory article.[^].
这篇关于人们将如何去做呢? (代码覆盖率)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!