drupsys / codeception-use-cases-module
支持基于用例测试的Codeception模块
Requires
- php: ^7.4|^8.0
- ext-redis: *
- drupsys/servicer-contracts: ^1.0
- guzzlehttp/guzzle: ^7.4
- lstrojny/functional-php: ^1.17
Requires (Dev)
- codeception/codeception: ^4.1
- codeception/module-asserts: ^2.0
- illuminate/database: ^8.79
- scheb/tombstone-logger: ^1.5
- symfony/var-dumper: ^5.4
This package is auto-updated.
Last update: 2024-08-31 00:27:46 UTC
README
这是一个用于基于用例测试的codeception模块,该模块旨在推广编写真实的单元测试,如Ian Cooper在“TDD,Where Did It All Go Wrong”演讲中所描述的。
相关参考
设置
假设您有tests/usecase.suite.yaml
文件,可以通过以下方式启用此模块:
actor: UseCaseTester modules: enabled: - \Helper\UseCase - \MVF\Codeception\UseCases\Module: providers: mysql: App\Providers\UseCases\EloquentProvider redis: App\Providers\UseCases\RedisProvider - Asserts
特别注意的是,将\MVF\Codeception\UseCases\Module
添加到模块列表中。此模块需要配置才能正确运行,必须定义providers
列表。
MySql Provider
这是一个必须实现MVF\Codeception\UseCases\Contracts\MySqlInterface
的对象,其外观可能如下所示。
namespace App\Providers\UseCases; use Illuminate\Database\Connection; use MVF\Codeception\UseCases\Contracts\MySqlInterface; class EloquentProvider implements MySqlInterface { public function __construct() {} public function getMySql(): Connection { return ...; // return writable eloquent connection, this connection should be privileged, able to write, read, delete and truncate tables. } }
Redis Provider
这是一个必须实现MVF\Codeception\UseCases\Contracts\RedisInterface
的对象,其外观可能如下所示。
namespace App\Providers\UseCases; use MVF\Codeception\UseCases\Contracts\RedisInterface; use Redis; class RedisProvider implements RedisInterface { public function __construct() {} public function getRedis(): Redis { return ...; // return redis object } }
服务
您的docker compose文件应包含以下服务:
<app>-test-mysql: container_name: <app>-test-mysql networks: [mvf_shared] image: mysql:5.7.26 environment: MYSQL_ROOT_PASSWORD: 12345 MYSQL_DATABASE: ... MYSQL_USER: ... MYSQL_PASSWORD: ... healthcheck: test: mysqladmin -uroot -p12345 ping -h localhost interval: 2s timeout: 20s retries: 10 volumes: - mysql-test:/var/lib/mysql:cached command: --server-id=1 --log-bin=test.log <app>-binlog-parser: build: context: build/binlog-parser container_name: <app>-binlog-parser networks: [mvf_shared] restart: always <app>-redis: container_name: <app>-redis networks: [mvf_shared] image: redis:6-alpine networks: mvf_shared: external: true
<app>-test-mysql
MySql服务应将MYSQL_ROOT_PASSWORD
设置为12345
,具有以下标志的命令:--server-id=1 --log-bin=test.log
,如果您已经定义了某些命令,只需将此标志附加到现有命令,并且应使用[mvf_shared]
网络。
<app>-binlog-parser
Maxwell服务也应使用[mvf_shared]
网络,并且应在build/binlog-parser
文件夹中构建。此文件夹应包含Dockerfile
和config.properties
文件。
以下是你Dockerfile
的内容,检查maxwell
和alpine
版本以查看是否有更新的版本可用。
FROM openjdk:18-ea-11-jdk-alpine3.15 RUN apk add --no-cache --update bash shadow RUN /usr/sbin/groupadd -g 1000 www RUN /usr/sbin/useradd -s /bin/sh -g 1000 -u 1000 www ENV MAXWELL_VERSION=1.35.5 COPY --from=zendesk/maxwell:v1.35.5 /app /app WORKDIR /app RUN chown 1000:1000 /app && echo "$MAXWELL_VERSION" > /REVISION USER 1000 COPY config.properties ./config.properties CMD [ "/bin/bash", "-c", "bin/maxwell", "--config=/app/config.properties" ]
以下是你config.properties
的内容。
log_level=info # mysql source config host=<app>-test-mysql user=root password=12345 # redis target config producer=redis redis_key=maxwell redis_type=xadd redis_host=<app>-redis redis_port=6379
此配置的大部分内容应该很直观,唯一需要说明的是redis_key
,这是Maxwell将所有bin日志数据存储的位置,默认情况下此键设置为maxwell
,但如果您已经在应用程序中使用此键,则需要更改其值。
如果您将redis_key
的值更改为testing
,则还必须在测试套件中提供额外的配置。假设您有tests/usecase.suite.yaml
,则新的redis_key
也必须在此处定义,如下所示。
actor: UseCaseTester modules: enabled: - \MVF\Codeception\UseCases\Module: providers: ... redis_key: testing # <- this needs to match redis key in config.properties
<app>-redis
Redis服务应像其他服务一样使用[mvf_shared]
网络。
需求和动机
为此模块正常工作,您将需要以下内容:
- 启用binlog的MySql测试数据库
- Maxwell守护进程读取binlog并将它们推送到Redis
- Redis缓存以存储binlog数据
此模块中有很多内容,我假设您会有很多问题,让我们先回答一些问题。
为什么我们需要启用binlog的mysql测试服务器?
简短的答案是,这是Maxwell守护进程了解数据库上执行了哪些变更所必需的。
什么是Maxwell守护进程?
这是一个消耗mysql binlog、将它们转换为简单的json对象并将它们发送到支持的目标之一的过程,在我们的案例中是一个Redis服务器。
为什么此模块需要Redis才能运行?
再次回答,简单地说,Maxwell 守护进程使用 Redis 作为 binlog 的存储。有许多不同的服务可以作为 Maxwell 守护进程存储 binlog 的位置,但 Redis 是最合适的,因为我们需要在 PHP 代码中读取存储的数据,从 Redis 中读取数据非常简单。
这一切的意义是什么?
增加的复杂性解决了我们与数据库重置相关的问题。我们正在使用的数据库在每次测试后大约需要 40 秒才能重置。Maxwell 守护进程使我们能够知道哪些表受到了影响,因此我们可以只截断必须截断的表。这提高了每次测试的速度大约 120 倍。
这也为我们提供了一种编写纯声明性测试的方法,在你的测试过程中任何时候都不需要与数据库交互或编写逻辑。编写测试的过程可以用以下步骤来概括
- 声明应用程序的
初始状态
- 运行待测试的代码
- 声明对应用程序的
最终状态
的断言
初始状态
只是一个关联数组,描述了代码执行之前应用程序的状态,而 最终状态
是一个关联数组,描述了代码执行之后应用程序的状态。