MsTest 数据驱动:通过 testattribute 忽略特定数据行?

发布于 2024-11-18 20:36:45 字数 2743 浏览 3 评论 0原文

我在 stackoverflow 上的第一个问题,我希望这不是一个愚蠢的问题。 :)

基本上我所有的数据驱动测试都是这样的:

[TestMethod]
[DataSource(TestsDataSource)]
public void Test_With_Some_Fancy_Name()
{
   if (myIsThisTestIgnored) return;
...

DataSource 属性 + app.config 连接字符串 + excel odbc 驱动程序 = excel 数据驱动测试。

myIsThisTestIgnored[TestInitialize] 方法中设置(对于每个数据行,都有一个带有单独 [TestInitialize] 的单独测试),通过 TestContext.DataRow["Ignore"],这样我就可以通过 Excel 工作表中的一些 true/false 来“忽略”测试。

现在我的问题是:只需从测试方法返回即可让测试通过。如何不让被忽略的测试在 MSTEST 测试运行程序中“通过”(以及通过 msbuild 在 CI 中),或者甚至更好,根本不显示它们?

在我们的 Ci Build 上,它总结了每个被忽略(也称为通过)的测试,因为测试计数是数据行 x 测试方法,从而对运行的测试数量给出了错误的印象。但是,到目前为止,我还没有找到以编程方式将测试结果设置为“忽略”(或“通过”/“失败”之外的任何其他状态)的方法。

此外,在每个测试中摆脱这个烦人的忽略行并增强断言消息而不将每个断言包装在某个函数中也会很好。

因此,我认为最好/唯一的方法是 AOP 风格编程和使用自定义属性。我发现这篇关于使用自定义属性增强 mstest 代码的旧文章,很好读: http: //callumhibbert.blogspot.com/2008/01/extending-mstest.html

具体来说,链接文章中的最后一条评论让我思考,因为这个人不仅通过展示如何访问而让我开心所有测试状态数据到属性(MarshalObject 的东西),但不知何故他让它工作,引用他“以这种方式,我可以确定是否基于来自数据驱动信息的矩阵来运行测试文本上下文(使用 DataSource 属性),以及我创建的新自定义属性“。 是的..但是该怎么做?

我拿了一些代码并实现了它,看起来像这样:

public class MyCustomAspect : TestAspect<MyCustomAttribute>, IMessageSink, ITestAspect
{ ....

    [SecurityPermission(SecurityAction.LinkDemand, Flags = SecurityPermissionFlag.Infrastructure)]
    public IMessage SyncProcessMessage(IMessage msg)
    { 
      ....
      // see last comment in linked article to how to get this MarshalObject
      MyTestsClass testClass = (MyTestsClass)MarshalObject;

      if(testClass.myTestInitializeRan && testClass.myIsThisTestIgnored)
      {
        // what to do here? I would like to get rid of the SyncProcessMessage invocation, but...
        // return msg or null -> Exception "The method was called with a Message of an unexpected type."
        // constructing a IMessage in an easy way (specifically CallMessage) seems not possible, and I have no clue how to construct a valid CallMessage that says "ignore test!"
      }
      else
      {
        IMessage message = _nextSink.SyncProcessMessage(msg);
        return message;
      }

再次:我想抑制这个数据行的测试运行,或者以某种方式将测试结果设置为“忽略”/“未知”。

对返回的 messagemsg 执行任何操作似乎毫无意义,因为 IMessage 接口只是公开了 Properties 字典,其中包含只有一些 MethodName 和其中的东西,看起来没什么有趣的。

IMessage 转换为具体实现是行不通的:它们都是 System.Runtime 的内部实现。尽管可以转换为 ResultMessage ,并且在引发异常时它会返回一些 != null (因此您可以获取异常消息并通过 new throw 调整错误消息)。

有什么想法吗?非常感谢您到目前为止的阅读。 ;)

my first question on stackoverflow and I'm hoping it's not a stupid one. :)

Basically all my datadriven tests look like this one:

[TestMethod]
[DataSource(TestsDataSource)]
public void Test_With_Some_Fancy_Name()
{
   if (myIsThisTestIgnored) return;
...

DataSource attribute + app.config connectionstring + excel odbc driver = excel datadriven tests.

myIsThisTestIgnored is set in the [TestInitialize] method (for every datarow there is a separate test with separate [TestInitialize]), via TestContext.DataRow["Ignore"], so I can "ignore" tests via some true/false in an excel sheet.

Now my problem is: just returning from a test method lets the test pass. How to not let the ignored tests "pass" in the MSTEST testrunner (and in the CI via msbuild), or even better, do not show them at all?

On our Ci Build, it sums up every ignored (a.k.a passed) test, as the count of test is datarows x number of testmethods, giving a faulty impression of the number of tests that ran. But, until now, I found no way to just set the test result to "ignored" (or any other state than "passes"/"failed") programmatically.

Besides, getting rid of this annoying ignore line in every test and enhancing the assert messages without wrapping every assert in some function would be nice, too.

So the best/only approach to this, I thought, would be AOP style programming and using custom attributes. I found this old post about enhancing your mstest code with custom attributes, good read: http://callumhibbert.blogspot.com/2008/01/extending-mstest.html

Specifically the last comment in the linked article got me thinking, as the guy not just made my day by showing how to access all test state data to the attribute (the MarshalObject stuff), but somehow he got it working, quoting him "In this manner, I can determine whether or not to run a test based on a matrix of data driven information from the text context (using the DataSource attribute), and the new custom attributes I created. ". Yeah.. but how to do that?

I took some of the code and implemeted it, looking something like that:

public class MyCustomAspect : TestAspect<MyCustomAttribute>, IMessageSink, ITestAspect
{ ....

    [SecurityPermission(SecurityAction.LinkDemand, Flags = SecurityPermissionFlag.Infrastructure)]
    public IMessage SyncProcessMessage(IMessage msg)
    { 
      ....
      // see last comment in linked article to how to get this MarshalObject
      MyTestsClass testClass = (MyTestsClass)MarshalObject;

      if(testClass.myTestInitializeRan && testClass.myIsThisTestIgnored)
      {
        // what to do here? I would like to get rid of the SyncProcessMessage invocation, but...
        // return msg or null -> Exception "The method was called with a Message of an unexpected type."
        // constructing a IMessage in an easy way (specifically CallMessage) seems not possible, and I have no clue how to construct a valid CallMessage that says "ignore test!"
      }
      else
      {
        IMessage message = _nextSink.SyncProcessMessage(msg);
        return message;
      }

Again: I want to suppress the testrun for this datarow, or set the testresult somehow to "ignore"/"unknown".

Doing anything with the returned message or msg seems pointless, as the IMessage Interface just exposes the Properties Dictionary which has only some MethodName and stuff in it, nothing interesting it seems.

Casting IMessage to concrete implementations doesn't work: they are all internal to System.Runtime. Though one can cast to ResultMessage and it returns something != null when an exception was raised (so you can take the exception message and adjust error message via new throw).

Any Ideas? And many thanks for reading so far. ;)

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

来世叙缘 2024-11-25 20:36:45

如何不让被忽略的测试在 MSTEST 测试运行程序中(以及通过 msbuild 在 CI 中)“通过”,或者更好的是,根本不显示它们?

如果您不希望将跳过的测试视为已通过,则可以使用 Assert.Fail 或 Assert.Inconclusive 而不是简单地从测试用例返回。

您还可以在 MSTest 中找到 带有测试属性的数据驱动测试< /a> 有用。作者展示了如何使用 postsharp 创建参数化行测试,以便跳过使用 excel 进行数据驱动测试的需要,而是将参数作为测试方法上方的属性发布。因此,当您想要删除或忽略测试用例时,您只需注释掉该数据行即可,它根本不会显示。

How to not let the ignored tests "pass" in the MSTEST testrunner (and in the CI via msbuild), or even better, do not show them at all?

You could use Assert.Fail or Assert.Inconclusive instead of simply returning from the test case if you do not want skipped tests to be accounted for as passed.

You may also find Data driven tests with test attributes in MSTest useful. The author showcases how to use postsharp to create parameterised Row tests in order to skip the need of using excel for data driven tests and instead post the parameters as an attribute above the test method. Therefore when you would like to remove or ignore a test case you would simply comment out that data row and it would not be shown at all.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文