基于场景的单元测试:组织
我和一个朋友最近遇到了 场景的想法基于的单元测试,我们认为这是每类测试用例方法的一个很好的替代方案。它特别有吸引力,因为它有助于整合我们的大部分设置代码并减少创建测试所需的时间。但是为每个场景创建一个新的测试夹具给我们带来了一个新问题:我们应该如何组织这些场景测试夹具?
如果我们为每个场景创建一个新的测试装置,我们将创建很多装置。我们把它们放在哪里?在一个庞大的文件中?或者我们应该为每个场景创建一个新文件,并将该文件与所有其他测试装置放在一个文件夹中?
我之所以问这个问题,是因为当我们稍后必须维护代码时,很可能会给我们自己带来很大的麻烦,但直到损坏发生之后我们才能知道这是一个令人头痛的事情。
A friend and I recently came across the idea of scenario-based unit testing, which we think is a great alternative to the test-case-per-class methodology. It's especially attractive because it helps consolidate much of our setup code and reduces the time it takes to create tests. But creating a new test fixture for each scenario gives us a new problem: How should we organize these scenario test fixtures?
If we create a new test fixture for each scenario, we will be creating a lot of fixtures. Where do we put them? In one single mammoth of a file? Or should we create a new file for each scenario, and place that file in a folder with all the other test fixtures?
The reason I ask is because there is great potential for creating a big headache for ourselves when we have to maintain our code later, but we won't be able to tell it's a headache until after the damage has been done.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
基于场景的测试很棒,并且关于如何组织测试当然有很多选择。
嵌套类
这种测试风格的一个关键要点是我们实际上使用嵌套类来表示我们的场景。我们创建一个根类来代表所有测试的容器,然后每个场景都是一个派生类。
在 NUnit 中,子类被展平,根和嵌套类名称显示为 Fixture 名称的一部分:
在我的项目中,我通常为每个主题创建一个类文件,并将所有场景保留为嵌套类。我使用 Visual Studio 的大纲来折叠嵌套类。通过这种方式,我可以很快地看到所有场景。
按场景归档
Dave 文章中有趣的一点是他使用了部分类。他这样做是因为这使得在 Resharper 中导航更加容易,但这也意味着灯具可以分解为不同的文件。
将灯具分成多个文件可能是一个品味问题,但这是一个非常有趣的想法。我可以看到这种情况崩溃的一个地方是文件使用的命名约定,特别是当场景名称很长或需要更改时。
就我个人而言,如果有必要的话,我只会分成多个文件。
每个测试策略的文件
虽然我个人不赞成将我的装置分成多个文件,但我认为这很有意义的一个方面是如果您有不同的测试策略。例如,考虑两种测试策略,其中一组单元测试使用 Mock 对象作为依赖项,另一组使用具体依赖项。
关于对测试装置使用子类的建议 - 这些测试的可读性是主要关注点 - 不要从测试中抽象出细节,并且不要创建使用多个继承级别的测试装置你会没事的。
Scenario-based testing is great and there are certainly a lot of options on how to organize your tests.
Nested Classes
A key take away from this style of testing is that we're actually using nested classes to represent our scenarios. We create a root class that represents the container for all the tests and then each scenario is a derived class.
Within NUnit, the subclasses are flattened out and the root and nested class name appear as part of the Fixture name:
In my projects, I typically create one class file per subject and keep all the scenarios as nested classes. I use Visual Studio's outlining to collapse the nested classes. In this fashion, I can see all the scenarios rather quickly.
File Per Scenario
One of the interesting points in Dave's post is that he's using partial classes. He's done so because it makes navigating within Resharper easier, but it also means that fixtures can broken down into different files.
Splitting the fixtures into multiple files may be a matter of taste, but it's a very interesting idea. One area where I could see this falling apart is the naming convention used for the files, especially if the scenario names are long or need to change.
Personally, I would only split into multiple files if it warranted it.
File Per Testing Strategy
While I'm personally not in favor of splitting my fixtures into multiple files, one area I can see this making a lot of sense is if you have different testing strategies. For example, consider two testing strategies where one set of unit tests use Mock objects as dependencies and another set using concrete dependencies.
A word of advise on using subclasses for test fixtures -- readability of these tests is the main concern -- don't get carried away with abstracting the details away from the test, and don't create test fixtures that use several levels of inheritance and you'll be fine.
您所描述的内容对我来说听起来很像 BDD(行为驱动开发)。从语义上讲,您谈论的是规范,而不是测试。你的规范被写成一系列场景,通常以“Given-When-Then”(简称 GWT)这样的格式编写。这意味着给定系统处于某种状态,当执行操作时,就会发生可观察到的变化。
有许多实现可以处理这个问题。我目前最喜欢的是 mspec(机器规范),这是一个在 NUnit 或 XUnit.Net 上工作的框架。其他包括 Specflow 和 RSpec(基于 ruby 的实现)。
MSpec 的优点之一是每个规范(测试)都是由定义初始状态、操作和预期结果(断言)的委托构建的。这意味着您可以在辅助类中定义其中的每一个,并根据需要调用它们,进行混合和匹配,而这是使用继承层次结构永远无法做到的。
希望这有帮助,
阿萨夫。
What you're describing sounds to me a lot like BDD - Behavior Driven Development. Semantically, you talk about specifications, rather than tests. And your specs are written as a series of scenarios, often written in a format like Given-When-Then (GWT for short). This means Given the system is in some state When an action is performed Then _an observable change occurs.
There are many implementations to handle this. My current favorite is mspec (machine specifications), a framework that works over NUnit or XUnit.Net. Others include Specflow, and RSpec (a ruby based implementation).
One of the nice things about MSpec, is that each spec (test) is constructed of delegates that define the initial state, the action and the expected results (asserts). This means that you can define each of these once in a helper class, and call them as needed, mixing and matching, which you could never do with an inheritance hierarchy.
Hope this helps,
Assaf.