如何简化这些 NUUnit 测试?

发布于 2024-09-01 08:07:58 字数 863 浏览 9 评论 0原文

这三个测试是相同的,只是它们使用不同的静态函数来创建 StartInfo 实例。我的测试代码中出现了这种模式,并且会喜欢 能够使用 [TestCase] 或任何其他减少样板代码的方式来简化这一过程。据我所知,我不允许使用委托作为 [TestCase] 参数,我希望这里的人们对如何使下面的代码更简洁有创造性的想法。

    [Test]
    public void ResponseHeadersWorkinPlatform1()
    {
        DoResponseHeadersWorkTest(Platform1StartInfo.CreateOneRunning);
    }
    [Test]
    public void ResponseHeadersWorkinPlatform2()
    {
        DoResponseHeadersWorkTest(Platform2StartInfo.CreateOneRunning);
    }
    [Test]
    public void ResponseHeadersWorkinPlatform3()
    {
        DoResponseHeadersWorkTest(Platform3StartInfo.CreateOneRunning);
    }

    void DoResponseHeadersWorkTest(Func<ScriptResource,StartInfo> startInfoCreator)
    {
        ScriptResource sr = ScriptResource.Default;
        var process = startInfoCreator(sr).Start();
        //assert some things here
    }

These three tests are identical, except that they use a different static function to create a StartInfo instance. I have this pattern coming up all trough my testcode, and would love
to be be able to simplify this using [TestCase], or any other way that reduces boilerplate code. To the best of my knowledge I'm not allowed to use a delegate as a [TestCase] argument, and I'm hoping people here have creative ideas on how to make the code below more terse.

    [Test]
    public void ResponseHeadersWorkinPlatform1()
    {
        DoResponseHeadersWorkTest(Platform1StartInfo.CreateOneRunning);
    }
    [Test]
    public void ResponseHeadersWorkinPlatform2()
    {
        DoResponseHeadersWorkTest(Platform2StartInfo.CreateOneRunning);
    }
    [Test]
    public void ResponseHeadersWorkinPlatform3()
    {
        DoResponseHeadersWorkTest(Platform3StartInfo.CreateOneRunning);
    }

    void DoResponseHeadersWorkTest(Func<ScriptResource,StartInfo> startInfoCreator)
    {
        ScriptResource sr = ScriptResource.Default;
        var process = startInfoCreator(sr).Start();
        //assert some things here
    }

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

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

发布评论

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

评论(2

鹿港巷口少年归 2024-09-08 08:07:58

首先,我不认为原著太糟糕。如果您的断言因测试用例而异,那么只会很混乱。

无论如何,您可以使用测试用例,但由于使用更复杂的类型,因此无法通过标准 [TestCase] 属性来完成。相反,您需要使用公共 IEnumerable<>作为数据提供者,然后使用 [TestCaseSource] 属性。

尝试类似的操作:

    public IEnumerable<Func<ScriptResource, StartInfo>> TestCases
    {
        get
        {
            yield return Platform1StartInfo.CreateOneRunning;
            yield return Platform2StartInfo.CreateOneRunning;
            yield return Platform3StartInfo.CreateOneRunning;
        }
    }

    [TestCaseSource("TestCases")]
    public void MyDataDrivenTest(Func<ScriptResource, StartInfo> startInfoCreator)
    {
        ScriptResource sr = ScriptResource.Default;
        var process = startInfoCreator(sr);

        // do asserts
    }
}

这是生成包含参数的 TestCaseData 实例的标准模式的更简洁版本。如果您生成 TestCaseData 的实例,您可以向每个测试添加更多信息和行为(如预期的异常、描述等),但它稍微冗长一些。

我真正喜欢这个东西的部分原因是你可以为你的“行为”制定一种方法,为你的“断言”制定一种方法,然后独立地混合和匹配它们。例如,我的朋友昨天在做某事,他使用两个 Action 来表示(“当调用方法 Blah 时,应该触发 ViewModel 上的此方法”)。非常简洁有效!

Firstly, I don't think the original is too bad. It's only messy if your assertions are different from test case to test case.

Anyway, you can use a test case, but it can't be done via a standard [TestCase] attribute due to using more complicated types. Instead, you need to use a public IEnumerable<> as the data provider and then tag your test method with a [TestCaseSource] attribute.

Try something like:

    public IEnumerable<Func<ScriptResource, StartInfo>> TestCases
    {
        get
        {
            yield return Platform1StartInfo.CreateOneRunning;
            yield return Platform2StartInfo.CreateOneRunning;
            yield return Platform3StartInfo.CreateOneRunning;
        }
    }

    [TestCaseSource("TestCases")]
    public void MyDataDrivenTest(Func<ScriptResource, StartInfo> startInfoCreator)
    {
        ScriptResource sr = ScriptResource.Default;
        var process = startInfoCreator(sr);

        // do asserts
    }
}

This is a more concise version of the standard pattern of yielding TestCaseData instances containing the parameters. If you yield instances of TestCaseData you can add more information and behaviours to each test (like expected exceptions, descriptions and so forth), but it is slightly more verbose.

Part of the reason I really like this stuff is that you can make one method for your 'act' and one method for your 'assert', then mix and match them independently. E.g. my friend was doing something yesterday where he used two Actions to say ("when method Blah is called, this method on the ViewModel should be triggered"). Very terse and effective!

江南烟雨〆相思醉 2024-09-08 08:07:58

看起来不错。您是否想增加一家工厂?或者您可以将这些方法添加到操作列表(在测试设置中)并调用第一个操作委托、第二个操作委托和第三个操作委托。

It looks good. Are you looking to add a factory maybe ? Or you could add these methods to a Action List(in test setup) and call first action delegate, second action delegate and third action delegate.

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