lifterlms / lifterlms-tests
LifterLMS项目的测试框架
Requires
- php: ^7.3 || ^8.0
- phpunit/phpunit: ^7.5 || ^9.5
- wp-cli/extension-command: ^2.1.13
- wp-cli/wp-cli-tests: ^4.2.9
- yoast/phpunit-polyfills: ^1.0
This package is auto-updated.
Last update: 2024-09-09 17:13:54 UTC
README
LifterLMS Tests是一个帮助在LifterLMS项目中启动自动化测试的项目。
安装
- 安装包:
composer require --dev lifterlms/lifterlms-tests
- 创建一个
phpunit.xml.dist
文件。参见示例。 - 添加一个
tests
目录:mkdir tests
- 在
tests
目录中创建一个引导文件。参见示例。 - 在
tests/unit-tests
中添加测试类
命令
- 安装测试套件:
./vendor/bin/llms-tests install <db-name> <db-user> <db-pass> [db-host] [wp-version] [skip-database-creation]
- 拆卸测试套件:
.vendor/bin/llms-tests teardown <db-name> <db-user> <db-pass> [db-host]
- 安装插件:
./vendor/bin/llms-tests plugin <slug_or_zip_giturl> [version]
- 运行测试:
./vendor/bin/phpunit
- 环境:
./vendor/bin/llms-env <command> [options]
。查看./vendor/bin/llms-env --help
获取完整文档。
环境
llms-env
命令提供了一套简单的工具,有助于管理和使用Docker容器进行LifterLMS插件的开发和测试。
对于定制,运行llms-env config
在项目根目录中创建推荐的docker-compose.yml
和.llmsenv
文件。
docker-compose.yml
会自动将根目录挂载到wp-content/plugin
目录。
.llmsenv
文件允许自定义WordPress用户名、localhost端口等。此文件是可选的,如果省略任何变量,将使用默认值。
配置好配置文件后,运行llms-env up
来创建容器、安装和配置WordPress。
如果需要其他插件或任何其他WordPress配置,尝试创建一个composer脚本,通过wp-cli
在主PHP服务容器上运行所需命令。例如,在您的composer.json中添加一个脚本
{ "scripts": { "env-setup": [ "./vendor/bin/llms-env wp plugin install lifterlms --activate" ] } }
这可以用来激活LifterLMS核心。
llms-env
提供了许多用于组合和管理Docker容器的命令。运行llms-env --help
获取可用命令的完整列表以及它们的使用信息。
预定义脚本
以下脚本可以添加到您的composer.json
文件中,以便轻松访问这些脚本,并确保在安装和更新包时自动设置配置。
"scripts": { "tests-install": [ "vendor/bin/llms-tests teardown llms_tests root password localhost", "vendor/bin/llms-tests install llms_tests root password localhost", "vendor/bin/llms-tests plugin lifterlms" ], "tests-run": [ "vendor/bin/phpunit" ] }
实用工具
实用方法位于LLMS_Unit_Test_Util
类中。
获取私有/受保护的类方法
$method = LLMS_Unit_Test_Util::get_private_method( new MyClass(), 'my_private_method' ); $method = LLMS_Unit_Test_Util::get_protected_method( new MyClass(), 'my_private_method' );
调用私有/受保护的类方法进行测试
$result = LLMS_Unit_Test_Util::call_method( new MyClass(), 'my_private_method', array( 'argument_1', 'arg_2', ... ) ); $this->assertTrue( $result );
函数
使用llms_tests_mock_current_time( $timestamp_or_date )
模拟llms_current_time()
的返回值
使用llms_tests_reset_current_time()
重置当前时间
测试用例方法
继承自LLMS_Unit_Test_Case
类的测试用例可以访问测试用例类中内置的实用函数。
断言
继承自LLMS_Unit_Test_Case
类的测试用例可以访问测试用例类中内置的实用函数。
资产
断言资产(脚本或样式)是否通过WordPress依赖管理类注册或排队(或相反,未注册或未排队)。
$type
是"script"或"style",$handle
是用于注册/排队的脚本的手柄。
- 断言脚本/样式已注册:
$this->assertAssetIsRegistered( $type, $handle )
- 断言脚本/样式未注册:
$this->assertAssetNotRegistered( $type, $handle )
- 断言脚本/样式已排队:
$this->assertAssetIsEnqueued( $type, $handle )
- 断言脚本/样式未被排队:
$this->assertAssetNotEnqueued( $type, $handle )
输出缓冲区
- 断言函数输出包含字符串:
$this->assertOutputContains( $contains, $callable, $args_array );
- 断言函数输出不包含字符串:
$this->assertOutputNotContains( $contains, $callable, $args_array );
- 断言函数输出为空:
$this->assertOutputEmpty( $callable, $args_array );
- 断言函数输出等于预期:
$this->assertOutputEquals( $expected, $callable, $args_array );
WP_Error
- 断言对象是
WP_Error
:$this->assertWPError( $wp_err );
- 断言
WP_Error
代码等于预期:$this->assertWPErrorCodeEquals( $code, $wp_err );
- 断言
WP_Error
消息等于预期:$this->assertWPErrorMessageEquals( $message, $wp_err );
- 断言
WP_Error
数据等于预期:$this->assertWPErrorDataEquals( $data, $wp_err );
模拟 $_GET
、$_POST
和 $_REQUEST
数据
通过 $this->mockGetRequest( array( 'var' => 'value' ) );
添加模拟 $_GET
数据
通过 $this->mockPostRequest( array( 'var' => 'value' ) );
添加模拟 $_POST
数据
模拟通过 wp_remote_request()
进行的 HTTP 请求。
在调用 wp_remote_request()
之前,运行 $this->mock_http_request( $url, $data, $fuzzy_match )
以设置下一次 wp_remote_request()
的期望返回值。
当运行 wp_remote_request()
时,模拟器将检查是否为 URL 添加了模拟。如果找到,它将短路 HTTP 请求并在任何远程连接之前提前返回(返回 $data
的值)。一旦找到并返回模拟,它将从模拟器数据中删除。如果您希望模拟多个连续的 URL,您可以多次调用 mock_http_request()
。匹配器始终返回 第一个 匹配项。因此,如果您希望对相同的 URL 进行多次模拟,请确保按照预期返回的顺序设置模拟。
您可以将完整的或部分 URL 作为 $url
参数指定。如果指定部分 URL,请使用 $fuzzy_match = true
来匹配 URL 部分。
public function test_mock_https_request() { // Mocks a WP REST post creation request. $this->mock_http_request( '/wp-json/wp/v2/posts', [ 'body' => '{"id":123,"title":"Mock Title",...}', 'response' => [ 'code' => 201, ], ], true ); $res = wp_remote_post( rest_url( '/wp-json/wp/v2/posts' ), [ 'body' => [ 'title' => 'Mock Title', ], ], ); $this->assertEquals( 201, wp_remote_retrieve_response_code( $res ) ); $this->assertEquals( 123, json_decode( wp_remote_retrieve_response_body( $res ) )['id'] ); } ##### Utility Methods + Get the output of a function: `$output = $this->get_output( $callable, $args_array );` ## Exceptions Included exceptions allow easy testing of methods which call `exit()` and `llms_redirect_and_exit()`. ##### LLMS_Unit_Test_Exception_Exit Test methods which call `exit()`: Call `$this->expectException( LLMS_Unit_Test_Exception_Exit::class );` before calling the function that calls exit. ```php public function test_example_exit() { $this->expectException( LLMS_Unit_Test_Exception_Exit::class ); example_function_that_exits(); }
LLMS_Unit_Test_Exception_Redirect
测试调用 llms_redirect_and_exit()
的方法
public function test_my_redirect_and_exit() { $this->expectException( LLMS_Unit_Test_Exception_Redirect::class ); $this->expectExceptionMessage( 'https://lifterlms.com [302] YES' ); llms_redirect_and_exit( 'https://lifterlms.com' ); }
异常会导致 PHP 执行停止。要在遇到异常后运行更多测试,请添加 try/catch 块
public function test_my_redirect_and_exit() { $this->expectException( LLMS_Unit_Test_Exception_Redirect::class ); $this->expectExceptionMessage( 'https://lifterlms.com [302] YES' ); try { llms_redirect_and_exit( 'https://lifterlms.com' ); } catch( LLMS_Unit_Test_Exception_Redirect $exception ) { // Any additional assertions can be added here. $this->assertTrue( ... ); throw $exception; } }
工厂
扩展 LLMS_Unit_Test_Case
类的测试用例可以访问基于 WP 单元测试工厂构建的工厂:WP_UnitTest_Factory_For_Post
和 WP_UnitTest_Factory_For_User
课程帖子工厂
访问工厂:$this->factory->course
创建一个课程并获取课程 ID:$course_id = $this->factory->course->create();
创建一个课程并获取 LLMS_Course 对象:$course = $this->factory->course->create_and_get();
创建多个课程:$courses = $this->factory->course->create_many( 5 );
指定章节、课程、测验和问题的数量
$args = array( 'sections' => 2, // 2 sections in the course 'lessons' => 5, // 5 lessons per section 'quizzes' => 1, // 1 quiz per section (will always be the last lesson in the section) 'questions' => 5, // 5 questions per quiz ); $course_id = $this->factory->course->create( $args ); $course = $this->factory->course->create_and_get( $args );
会员帖子工厂
访问工厂:$this->factory->membership
创建一个会员并获取会员 ID:$membership_id = $this->factory->membership->create();
创建一个会员并获取 LLMS_Membership 对象:$membership = $this->factory->membership->create_and_get();
创建多个会员:$memberships = $this->factory->membership->create_many( 5 );
订单帖子工厂
访问工厂:$this->factory->order
创建一个订单并获取订单 ID:$order_id = $this->factory->order->create();
创建一个订单并获取 LLMS_Order 对象:$order = $this->factory->order->create_and_get();
创建多个订单:$orders = $this->factory->order->create_many( 5 );
创建一个订单并为其记录交易:LLMS_Order:$order = $this->factory->order->create_and_pay();
学生用户工厂
访问工厂:$this->factory->student
创建一个学生并获取学生 ID:$student_id = $this->factory->student->create();
创建学生并获取LLMS_Student对象:$student = $this->factory->student->create_and_get();
创建多个学生:$students = $this->factory->student->create_many( 5 );
创建学生并注册课程/会员
$course_id = $this->factory->course->create(); // single student $student_id = $this->factory->student->create_and_enroll( $coursed_id ); // multiple students $student_ids = $this->factory->student->create_and_enroll_many( 5, $coursed_id );
讲师用户工厂
访问工厂:$this->factory->instructor
创建讲师并获取讲师ID:$instructor_id = $this->factory->instructor->create();
创建讲师并获取LLMS_Instructor对象:$instructor = $this->factory->instructor->create_and_get();
Cookie
使用LLMS_Tests_Cookies
类测试通过llms_setcookie
设置的cookie的方法和函数。
访问类:$this->cookies
.
设置cookie
$this->cookies->set( $name, $value, ... )
检索设置的cookie(s)
$this->cookies->set( 'name', 'value', 0, ... ); // Retrieve all cookies $cookies = $this->cookies->get_all(); var_dump( $cookies ); // array( // 'name' => array( // 'value' => 'value', // 'expires' => 0, // ... // ), // ) // // Retrieve a single cookie. $cookie = $this->cookies->get( 'name' ); var_dump( $cookie ); // array( // 'value' => 'value', // 'expires' => 0, // ... // ),
模拟llms_setcookie()的预期响应
模拟成功响应
$this->cookies->expect_success(); $this->assertTrue( llms_setcookie( 'name', 'val' ) );
在测试套件中,llms_setcookie()
总是响应true
,所以不需要调用expect_success()
,除非你之前在同一测试中调用了expect_error()
。
模拟错误响应
$this->cookies->expect_error(); $this->assertFalse( llms_setcookie( 'name', 'val' ) );
清除设置的cookie(s)
清除所有cookie
$this->cookies->unset_all() var_dump( $this->cookies->get_all() ); // array()
通过名称清除单个cookie
llms_setcookie( 'name', 'val' ); $this->cookies->unset( 'name' ); var_dump( $this->cookies->get( 'name' ) ); // null