测试类型

运行 PHPUnit 测试可以非常快。根据我的经验,即使有数以万计的单元测试,完全运行它们也只需几分钟。这是因为它们只测试解决方案的一小部分或单元。

我们还可以添加调用与外部网络服务 API 或数据库交互的程序的测试。现在,想象一下这些测试有多复杂,执行这些测试需要多长时间。如果我们将所有使用多个对象和单元测试的复杂测试合并为一组,那么运行整组测试将耗费大量时间。我曾在一家公司工作过,那里有成千上万的测试,这些测试都被组合成一个测试套件,你运行这个套件并等待一个小时,却发现有一个单元测试出了问题。这非常耗时,而且不切实际。

image 2023 10 23 16 37 03 024
Figure 1. Figure 5.13 – Grouping tests

确定测试的作用,并将其归入正确的测试组或测试筐,有助于组织测试。我们可以用不同类型的测试作为测试 "篮子" 或测试组。我们可以简化这些篮子,将其分为两大类型。在 PHPUnit 中,这些篮子被称为测试套件。

篮子 1 – 单元测试

本章前面我们已经编写了单元测试。如果你还记得,我们在 codebase/symfony/tests 目录下创建了一个名为 Unit 的目录。这将是我们的单元测试篮子。每一个专门测试解决方案的小部分或单元的测试都将放在这个目录下,而命名空间则如下: App/Tests/Unit

打开 codebase/symfony/phpunit.xml,你会发现我们在 tests/Unit/ 目录中声明了一个名为 Unit 的测试套件。我们将使用测试套件对测试进行分组和隔离。当我们想隔离要运行的测试组时,这将派上用场:

<testsuites>
    <testsuite name="Project Test Suite">
        <directory>tests</directory>
    </testsuite>
    <testsuite name="Unit">
        <directory>tests/Unit/</directory>
    </testsuite>
</testsuites>

这意味着如果我们想要运行单元测试套件,PHPUnit 将在 tests/Unit/ 目录中找到所有测试。

要运行该单元篮或测试套件内的所有测试,请运行以下命令:

/var/www/html/symfony# ./runDebug.sh --testsuite Unit

您将得到以下结果:

image 2023 10 23 16 43 14 345
Figure 2. Figure 5.14 – Unit test suite

通过添加 --testsuite unit 选项,我们确保仅在 App\Tests\Unit 命名空间内运行测试。这将帮助我们将测试执行集中在特定的篮子或测试套件上。

我们已经涵盖了第一组或第一篮子测试。我们创建了一个名为 Unit 的目录,这是我们将放置所有未来单元或简单测试的地方。接下来,我们需要创建一个单独的组或篮子来进行更复杂的测试。

篮子 2 – 集成测试

集成测试旨在测试解决方案的更大一部分。集成测试不是测试应用程序的一个小单元,而是在一次测试中涵盖解决方案的不同部分。

试想一下,测试一个使用其他对象的对象方法。测试的成功与否取决于外部因素,如数据库连接、API 调用或对其他类的依赖,而其他类也依赖于其他类。这就像规模稍大的单元测试。

例如,如果你有一个类要计算一些总数,然后将其持久化到数据库中,那么你就需要有一个测试来检查持久化到数据库中的计算结果。这就是集成测试非常有用的地方。

我们之前为单元测试创建了一个目录,现在让我们创建一个包含集成测试的目录。在 tests 目录下创建 Integration 目录:

/var/www/html/symfony# mkdir tests/Integration

创建 Integration 目录后,我们需要让 PHPUnit 知道这个目录。我们需要添加 Integration 测试套件并声明目录路径。打开 codebase/symfony/phpunit.xml 并使用以下配置:

codebase/symfony/phpunit.xml
<php>
    <ini name="display_errors" value="1" />
    <ini name="error_reporting" value="-1" />
    <server name="APP_ENV" value="test" force="true" />
    <server name="SHELL_VERBOSITY" value="-1" />
    <server name="SYMFONY_PHPUNIT_REMOVE" value="" />
    <server name="SYMFONY_PHPUNIT_VERSION" value="9.5" />
    <env name="SYMFONY_DEPRECATIONS_HELPER" value="disabled" />
</php>

<testsuites>
    <testsuite name="Project Test Suite">
        <directory>tests</directory>
    </testsuite>
    <testsuite name="Unit">
        <directory>tests/Unit/</directory>
    </testsuite>
    <testsuite name="Integration">
        <directory>tests/Integration/</directory>
    </testsuite>
</testsuites>

<coverage processUncoveredFiles="true">
    <include>
        <directory suffix=".php">src</directory>
    </include>
</coverage>

<listeners>
    <listener class="Symfony\Bridge\PhpUnit\SymfonyTestsListener" />
</listeners>

现在,Integration 测试套件已经注册。有了它,我们仍然可以在运行测试时通过 --testsuite 选项的 Unit 参数安全地运行单元测试。要运行集成测试,我们只需使用 --testsuite Integration 即可:

/var/www/html/symfony# ./runDebug.sh --testsuite Integration

由于我们没有测试,运行上述命令将返回以下结果:

image 2023 10 23 16 57 42 267
Figure 3. Figure 5.15 – Integration test suite

现在,我们有了一个可以放置所有集成测试的篮子,让我们开始编写第一个集成测试!

我们已经有了一个经过单元测试的类 Calculate.php。现在,如果我们能把它作为集成测试示例的一部分,那就再好不过了。