PHPUnit 组织测试的最佳实践

2022-01-25 00:00:00 php phpunit

我目前打算从头开始为一个项目进行 phpunit 测试.所以我正在研究一些项目(比如 Zend),看看他们是如何做事的,以及他们如何组织他们的测试.

I am currently going to start from scratch with the phpunit tests for a project. So I was looking into some projects (like Zend) to see how they are doing things and how they organizing their tests.

大部分事情都很清楚,唯一让我有问题的是如何正确组织测试套件.Zend 有一个 AllTests.php,可以从中加载其他测试套件.
仔细查看它正在使用 PHPUnit_Framework_TestSuite 创建套件对象然后将其他套件添加到其中的类,但是如果我查看 PHPUnit 文档以在 3.4 之后的 PHPUnit 版本中组织测试,则只有一个XML 或 FileHierarchy 的描述.使用类来组织测试的那个被删除了.
我还没有发现这种方法已被弃用,像 Zend 这样的项目仍在使用它.

Most things are pretty clear, only thing I have some problems with is how to organize the test suites properly. Zend has an AllTests.php from which loads others test suites.
Tough looking at the class it is useing PHPUnit_Framework_TestSuite to create a suite object and then add the other suites to it, but if I look in the PHPUnit docs for organizing tests in PHPUnit versions after 3.4 there is only a description for XML or FileHierarchy. The one using classes to organize the tests was removed.
I haven't found anything that this method is deprecated and projects like Zend are still using it.

但如果它已被弃用,我将如何使用 xml 配置以相同的结构组织测试?执行所有测试没有问题,但是如果我只想执行几个测试,我将如何组织测试(在 xml 中).也许创建几个xml,我只指定几个要运行的测试/测试套件?

But if it is deprecated, how would I be able to organize tests in the same structure with the xml configuration? Executing all tests is no problem, but how would I organize the tests (in the xml) if I only wanted to execute a few tests. Maybe creating several xmls where I only specify a few tests/test suites to be run?

因此,如果我只想测试应用程序的模块 1 和模块 2,我是否会为每个模块提供一个额外的 xml,并仅为其中的那些模块(模块使用的类)定义测试套件.还有一个为所有测试定义了一个测试套件?

So if I would want to only test module1 and module2 of the application, would I have an extra xml for each and defining test suites only for those modules (classes used by the module) in it. And also one that defines a test suite for all tests?

或者在特定测试上使用 @group 注释将它们标记为模块 1 或模块 2 会更好吗?

Or would it be better to use the @group annotation on the specific tests to mark them to be for module1 or module2?

提前感谢您向我指出一些最佳做法.

Thanks in advance for pointing me to some best practices.

推荐答案

我将从链接到手册开始,然后进入我在该领域的所见所闻.

I'll start of by linking to the manual and then going into what I've seen and heard in the field.

组织 phpunit 测试套件

我推荐的方法是将文件系统与 xml 配置相结合.

My recommended approach is combining the file system with an xml config.

tests/
  unit/
 | - module1
 | - module2
 - integration/
 - functional/

用一个phpunit.xml用一个简单的:

<testsuites>
  <testsuite name="My whole project">
    <directory>tests</directory>
  </testsuite>
</testsuites>

您可以根据需要拆分测试套件,但这是一个项目到项目的选择.

you can split the testsuites if you want to but thats a project to project choice.

运行 phpunit 将执行所有测试,运行 phpunit tests/unit/module1 将运行 module1 的所有测试.

Running phpunit will then execute ALL tests and running phpunit tests/unit/module1 will run all tests of module1.

这里最常见的方法是在 tests/unit/ 文件夹结构中镜像您的 source/ 目录结构.

The most common approach here is to mirror your source/ directory structure in your tests/unit/ folder structure.

无论如何,每个 ProductionClass 都有一个 TestClass,所以在我的书中这是一个很好的方法.

You have one TestClass per ProductionClass anyways so it's a good approach in my book.

  • 每个文件一个类.

如果您在一个文件中有多个测试类,那么无论如何它都不会工作,所以要避免这个陷阱.

It's not going to work anyways if you have more than one test class in one file so avoid that pitfall.

  • 没有测试命名空间

它只是让编写测试更加冗长,因为您需要一个额外的 use 语句,所以我会说 testClass 应该与生产类在同一个命名空间中,但这不是 PHPUnit 强制您做的.我只是发现它更容易,没有缺点.

It just makes writing the test more verbose as you need an additional use statement so I'd say the testClass should go in the same namespace as the production class but that is nothing PHPUnit forces you to do. I've just found it to be easier with no drawbacks.

例如 phpunit --filter Factory 执行所有 FactoryTests 而 phpunit tests/unit/logger/ 执行所有与日志记录相关的内容.

For example phpunit --filter Factory executes all FactoryTests while phpunit tests/unit/logger/ executes everything logging related.

您可以将 @group 标签用于问题编号、故事或其他内容,但模块"除外.我会使用文件夹布局.

You can use @group tags for something like issue numbers, stories or something but for "modules" I'd use the folder layout.

如果你想创建多个 xml 文件会很有用:

It can be useful to create multiple xml files if you want to have:

  • 没有代码覆盖率
  • 仅用于单元测试(但不适用于功能、集成或长期运行测试)
  • 其他常见的过滤器"案例
  • 例如 PHPBB3 为 他们的 phpunit.xmls

因为它与开始一个带有测试的新项目有关:

As it is related to starting a new project with tests:

  • 我的建议是使用 @covers 标签 就像我的博客中描述的那样(仅用于单元测试,始终覆盖所有非公共功能,始终使用覆盖标签.
  • 不要为您的集成测试生成覆盖率.它会给你一种虚假的安全感.
  • 始终使用白名单来包含您的所有生产代码,这样数字就不会骗您!
  • My suggestion is to use @covers tags like described in my blog (Only for unit tests, always cover all non public functions, always use covers tags.
  • Don't generate coverage for your integration tests. It gives you a false sense of security.
  • Always use whitelisting to include all of your production code so the numbers don't lie to you!

您的测试不需要任何类型的自动加载.PHPUnit 会解决这个问题.

You don't need any sort of auto loading for your tests. PHPUnit will take care of that.

使用 <phpunit bootstrap="file"> 属性来指定您的测试引导程序.tests/bootstrap.php 是放置它的好地方.在那里你可以设置你的应用程序自动加载器等等(或者调用你的应用程序引导程序).

Use the <phpunit bootstrap="file"> attribute to specify your test bootstrap. tests/bootstrap.php is a nice place to put it. There you can set up your applications autoloader and so on (or call your applications bootstrap for that matter).

  • 几乎所有事情都使用 xml 配置
  • 单独的单元和集成测试
  • 您的单元测试文件夹应该反映您的应用程序文件夹结构
  • 要仅执行特定测试,请使用 phpunit --filterphpunit tests/unit/module1
  • 从一开始就使用 strict 模式,永远不要关闭它.
  • Sebastian Bergmanns 银行账户"示例项目
  • phpBB3 即便如此,他们也不得不用他们的遗产与一些人抗争;)
  • Symfony2
  • Doctrine2
  • Sebastian Bergmanns "Bank Account" example project
  • phpBB3 Even so they have to fight some with their legacy ;)
  • Symfony2
  • Doctrine2

相关文章