包含 XML 作为单元测试的嵌入式资源?

发布于 12-08 13:39 字数 567 浏览 0 评论 0原文

我有通过序列化 XML 文件来初始化的对象。

我正在考虑将测试数据作为嵌入式资源包含在测试项目中,而不是在测试方法本身中“硬编码”数据。

嵌入式硬编码方法:

[Test]
public void IsMale_CheckIfGenderIsMale_ReturnsTrue()
{
Human human = new Human();
human.Gender = Gender.Male;
Gender expected = Gender.Male;
Assert.IsTrue((human.Gender == expected));
}

XML 方法:

[Test]
public void IsMale_CheckIfGenderIsMale_ReturnsTrue()
{
Human human = Human.Initialize("Human_Male.xml");
Gender expected = Gender.Male;
Assert.IsTrue((human.Gender == expected));
}

哪种方法更好?

I have objects that gets initialized by serializing an XML file.

I'm thinking of including the test data in the test project as an embedded resource instead of "hard-coding" the data in the test method itself.

Embedded Hard-coded approach:

[Test]
public void IsMale_CheckIfGenderIsMale_ReturnsTrue()
{
Human human = new Human();
human.Gender = Gender.Male;
Gender expected = Gender.Male;
Assert.IsTrue((human.Gender == expected));
}

XML approach:

[Test]
public void IsMale_CheckIfGenderIsMale_ReturnsTrue()
{
Human human = Human.Initialize("Human_Male.xml");
Gender expected = Gender.Male;
Assert.IsTrue((human.Gender == expected));
}

Which is a better approach?

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

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

发布评论

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

评论(2

柳若烟2024-12-15 13:39:37

我们经常在项目中使用嵌入的xml文件进行测试。因为我们要使用xml来测试对象的创建。

将对象的创建与类本身分开也是一种很好的做法,例如:

Human human = HumanFactory.Create("Human_Male.xml");

人类类将有一个构造函数,该构造函数接受性别等参数,并且可以从 HumanFactory 类中调用。这是一种关注点分离,可以将类的逻辑与构建类的机制分开。

当您需要一个人类对象进行测试时,您可以选择直接创建它或使用工厂并从 xml 创建它。

我还将进一步简化 HumanFactory 类,为其提供 xml 字符串(或 Stream)而不是文件名。这可以使测试更容易 - 因为您只需将 xml 包含在测试代码中而不是文件中:

Human human = HumanFactory.Create("<human gender="m"></human>");
Assert.AreEqual(human.Gender,  Gender.Male);

否则,您的测试取决于:

  1. 将“Human_Male.xml”文件部署到文件系统的测试设置代码,以及之后将其删除。尽管 Visual Studio 测试有一个很好的机制来执行此操作(测试设置部署会将文件复制到测试运行文件夹中,作为测试运行设置的一部分)。
  2. 在测试代​​码中包含嵌入资源的路径。如果您应该重组项目布局,则需要更改测试代码以匹配。并确保使用相对路径。

We often use embedded xml files in our project for testing. Because we want to test the creation of objects using xml.

It is also good practice to separate the creation of objects from the class itself, for example:

Human human = HumanFactory.Create("Human_Male.xml");

The human class would then have a constructor which takes parameters like gender, and can be called from the HumanFactory class. It's a separation of concerns that will keep the logic of your class separate from the mechanism of building it.

And when you need a human object for a test, you can choose either to create it directly or use the factory and create it from xml.

I would also simplify the HumanFactory class further, by giving it an xml string (or Stream) instead of a filename. This can make it easier to test - because you can just include the xml in your test code and not in a file:

Human human = HumanFactory.Create("<human gender="m"></human>");
Assert.AreEqual(human.Gender,  Gender.Male);

Otherwise your test depends on either:

  1. the test setup code deploying the "Human_Male.xml" file to the file system, and removing it afterwards. Although Visual Studio test has a nice mechanism to do this (test settings deployment will copy files into the test run folder as part of the test run setup).
  2. Including a path to the embedded resource in your test code. If you should ever restructure your project layout, you will need to change the test code to match. And make sure you use a relative path.
隔纱相望2024-12-15 13:39:37

外部文件的唯一问题是它们可能会发生变化。

我的首选选择是在测试文件中包含一系列初始化函数,可以根据需要从测试方法中调用这些初始化函数。这也使得可能在六个月内学习您的代码的其他人甚至您自己能够更轻松、更快速地阅读。

另一种选择是将一些对象类基于接口/抽象类型,以便您可以通过创建测试类来模拟它们(即使在运行时代码中)。
例如(与代码无关):

基本抽象类/接口:IHuman IHuman.Gender
属性/属性 IHuman.Height 属性/属性 IHuman.Weight
属性/属性

类 HumanMale 继承 IHuman HumanMale.Gender 覆盖 IHuman
性别返回男性。

类 HumanFemale 继承 IHuman HumanFemale.Gender 覆盖 IHuman
性别返回女性。

然后所有代码都使用 IHuman,您甚至可以使用工厂来创建 IHuman 类型来创建网络人军团:)

The only problem with external files is that they may change.

My preferred option is to have a series of initialisation functions within the test file that can be called from the test method as and when required. This also makes for easier and quicker reading for others that may pick up your code, or even yourself in six months time.

Another option is to base some of your object classes around an interface/abstract type so that you can mock them (even in your runtime code) by creating a test class instead.
For example (code agnostic):

base abstract class/interface: IHuman IHuman.Gender
property/attribute IHuman.Height property/attribute IHuman.Weight
property/attribute

class HumanMale inherits IHuman HumanMale.Gender overrides IHuman
Gender to return Male.

class HumanFemale inherits IHuman HumanFemale.Gender overrides IHuman
Gender to return Female.

All code then uses IHuman and you can even use a factory to create IHuman types to create a legion of cybermen :)

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