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