Laravel 12 测试体系:Pest v3 集成与测试策略
Laravel 12 测试体系:Pest v3 集成与测试策略
摘要
本文深入剖析 Laravel 12 与 Pest v3 的深度集成,从测试架构设计原理到具体实现细节,全面覆盖测试用例编写、测试套件组织、Mock 与 Stub 使用、测试覆盖率分析等核心领域。提供完整的测试策略体系,涵盖单元测试、集成测试、功能测试、API 测试和端到端测试,结合实际项目场景,帮助开发者构建高质量、可维护的 Laravel 应用。通过专业的测试技术和最佳实践,确保应用在各种场景下的可靠性和稳定性,为持续集成和持续部署提供坚实的质量保障。
1. Laravel 测试体系概述
Laravel 12 构建了一个完整、分层的测试生态系统,基于 PHPUnit 和 Pest v3,从单元测试到端到端测试,提供了全面的工具和辅助函数,帮助开发者构建高质量、可维护的应用。Laravel 的测试体系设计遵循测试金字塔原则,强调从底层到顶层的全面覆盖,确保应用在各种场景下的可靠性和稳定性。
1.1 核心测试功能
- PHPUnit 集成:内置 PHPUnit 支持,作为底层测试框架,提供完整的断言和测试运行器
- Pest v3 集成:官方推荐的测试框架,基于 PHPUnit 构建,提供更简洁、更优雅的测试语法
- 测试辅助函数:丰富的测试辅助方法,简化测试代码编写,如
actingAs()、get()、post()等 - 测试数据库:支持 SQLite 内存数据库、MySQL、PostgreSQL 等多种测试数据库,自动管理数据库连接
- 事务性测试:自动回滚数据库操作,确保测试隔离,避免测试之间的相互影响
- 浏览器测试:使用 Laravel Dusk 进行端到端测试,支持 JavaScript 交互和浏览器自动化
- API 测试:专门的 API 测试辅助函数,简化 HTTP 请求和响应断言,支持 JSON 和 XML 响应
- Mock 与 Stub:内置的模拟功能,支持依赖注入的测试,包括 Facade 模拟和服务容器模拟
- 测试覆盖率:支持代码覆盖率分析,帮助识别未测试的代码,集成 Xdebug 和 PHP_CodeCoverage
- 测试环境配置:独立的测试环境配置,避免影响开发和生产环境,支持环境变量和配置文件
- 并行测试:支持并行运行测试,显著提高测试执行速度,特别是在大型项目中
- 测试套件组织:灵活的测试套件组织方式,支持按功能、模块或测试类型分组
- 测试数据生成:内置的模型工厂和测试数据生成器,简化测试数据的创建和管理
1.2 测试类型与应用场景
| 测试类型 | 描述 | 适用场景 | 工具 | 执行速度 | 维护成本 | 最佳实践 |
|---|---|---|---|---|---|---|
| 单元测试 | 测试单个类或方法的功能,隔离外部依赖 | 业务逻辑、工具类、服务、模型方法 | Pest/PHPUnit | 极快 (毫秒级) | 低 | 使用 Mock/Stub 隔离依赖,测试边界情况和异常 |
| 集成测试 | 测试多个组件的交互,验证协作正确性 | 控制器、服务、数据库、队列、邮件 | Pest/PHPUnit + 测试数据库 | 中等 (秒级) | 中 | 使用事务性测试,避免测试数据污染 |
| 功能测试 | 测试完整的用户流程,模拟用户交互 | 注册、登录、购物车、支付、订单流程 | Pest/PHPUnit + 测试浏览器 | 中等 (秒级) | 中 | 测试核心用户旅程,避免测试实现细节 |
| API 测试 | 测试 API 端点的响应,验证数据格式和状态码 | RESTful API、GraphQL、WebSocket | Pest/PHPUnit + API 测试助手 | 快 (毫秒级) | 中 | 测试成功和失败场景,验证响应结构和 headers |
| 浏览器测试 | 测试浏览器交互和 JavaScript,端到端验证 | 前端交互、表单验证、SPA、复杂 UI 流程 | Laravel Dusk + ChromeDriver | 慢 (秒级/分钟级) | 高 | 专注于核心用户流程,使用页面对象模式 |
| 性能测试 | 测试应用的性能和响应时间,识别瓶颈 | API 响应、数据库查询、页面加载、并发处理 | Laravel Benchmark + 压测工具 | 中等 (秒级/分钟级) | 中 | 建立性能基线,监控关键指标变化 |
| 安全测试 | 测试应用的安全性,识别漏洞 | 认证、授权、输入验证、SQL 注入、XSS | Pest/PHPUnit + 安全工具 | 中等 (秒级) | 高 | 集成安全扫描工具,定期运行安全测试 |
| 冒烟测试 | 测试应用的基本功能,确保关键路径可用 | 部署验证、主要功能检查 | Pest/PHPUnit | 快 (秒级) | 低 | 包含核心功能测试,作为部署前检查 |
| 回归测试 | 测试应用的现有功能,确保修改不破坏现有功能 | 代码修改、依赖更新、重构 | Pest/PHPUnit | 中等 (秒级/分钟级) | 中 | 自动化运行,与 CI/CD 集成 |
1.3 测试金字塔策略
Laravel 推荐采用测试金字塔策略,构建分层的测试体系,确保测试的有效性和效率:
底层(基础):大量的单元测试(70-80%)
- 测试目标:单个组件的功能,如服务、工具类、模型方法等
- 技术特点:隔离外部依赖,使用 Mock/Stub,执行速度快(毫秒级)
- 价值:提供快速反馈,捕获大多数逻辑错误,维护成本低
- 最佳实践:测试边界情况、异常处理、核心业务逻辑
中层(桥梁):适量的集成测试和 API 测试(15-20%)
- 测试目标:组件之间的交互,如控制器与服务、服务与数据库等
- 技术特点:验证协作正确性,使用事务性测试,执行速度中等(秒级)
- 价值:确保系统各部分协同工作,验证业务流程的正确性
- 最佳实践:测试完整的业务流程,验证数据库操作,测试 API 响应
顶层(验证):少量的浏览器测试(5-10%)
- 测试目标:完整的用户流程,如注册、登录、购物车等
- 技术特点:端到端验证,支持 JavaScript 交互,执行速度慢(秒级/分钟级)
- 价值:验证前端和后端的集成,确保关键用户场景的正确性
- 最佳实践:专注于核心用户流程,使用页面对象模式,避免测试实现细节
测试金字塔的优势:
- 快速反馈:底层测试执行速度快,能快速发现问题
- 成本效益:底层测试维护成本低,上层测试维护成本高
- 全面覆盖:从单元到端到端的全面测试覆盖
- 可靠性:多层测试确保系统的可靠性和稳定性
实施建议:
- 根据项目规模和复杂度调整测试比例
- 优先编写单元测试,确保核心逻辑的正确性
- 为关键业务流程编写集成测试
- 为核心用户旅程编写浏览器测试
- 集成测试覆盖率工具,监控测试覆盖情况
1.4 测试环境配置
基础配置
1 | // phpunit.xml |
测试环境变量
1 | # .env.testing |
2. Pest v3 集成
Laravel 12 官方推荐使用 Pest v3 作为测试框架,基于 PHPUnit 构建,提供了更简洁、更优雅的测试语法,同时保留了 PHPUnit 的全部功能。Pest v3 引入了许多新特性,如更强大的数据提供者、更灵活的测试分组、更好的类型提示支持等。
2.1 安装与配置
安装 Pest v3
1 | # 安装核心包 |
配置 Pest
1 | // tests/Pest.php |
2.2 Pest v3 高级语法特性
测试分组与描述
Pest v3 提供了强大的测试分组和描述功能,帮助你组织测试代码并提高可读性。
1 | // 基本测试分组 |
数据提供者
Pest v3 提供了强大的数据提供者功能,允许你使用不同的数据集运行同一个测试,提高测试覆盖率和代码复用性。
1 | // 基本数据提供者 |
测试过滤器
Pest v3 提供了强大的测试过滤器功能,允许你控制哪些测试运行,哪些测试跳过,以及如何组织测试。
1 | // 标记测试 - 使用分组管理测试 |
并行测试
Pest v3 提供了强大的并行测试功能,允许你同时运行多个测试进程,显著提高测试执行速度,特别是在大型项目中。
1 | // 配置并行测试 |
测试生命周期钩子
Pest v3 提供了强大的测试生命周期钩子,允许你在测试执行的不同阶段运行代码,如测试前准备、测试后清理等。
1 | // 测试套件级别的生命周期钩子 |
3. 单元测试
单元测试是测试金字塔的基础,专注于测试单个类或方法的功能,确保每个组件都能按预期工作。
3.1 编写高质量单元测试
编写高质量的单元测试需要遵循一定的原则和最佳实践,以确保测试的有效性、可靠性和可维护性。以下是编写高质量单元测试的核心原则:
- 隔离性:单元测试应该独立运行,不依赖外部资源(如数据库、网络服务),使用 Mock/Stub 隔离外部依赖
- 原子性:每个单元测试应该只测试一个特定的功能点,确保测试的专注性和准确性
- 可重复性:单元测试应该能够重复运行并产生相同的结果,不受外部环境影响
- 清晰性:测试代码应该清晰易懂,包含明确的准备、执行和断言步骤
- 全面性:测试应该覆盖正常场景、边界情况和异常情况,确保代码的健壮性
- 可维护性:测试代码应该易于维护,遵循与生产代码相同的编码标准
测试服务类
1 | // tests/Unit/Services/UserServiceTest.php |
测试工具类
1 | // tests/Unit/Helpers/StrHelperTest.php |
3.2 高级模拟技术
高级模拟技术是编写高质量单元测试的关键,它允许你隔离外部依赖,控制测试环境,确保测试的可重复性和可靠性。Laravel 提供了多种模拟工具,包括 Mockery、PHPUnit 模拟对象和 Laravel 内置的 Facade 模拟。
使用 Mockery 进行高级模拟
1 | // tests/Unit/Services/PaymentServiceTest.php |
使用 Laravel 的模拟辅助函数
1 | // tests/Unit/Controllers/UserControllerTest.php |
3.3 边界情况和异常测试
边界情况和异常测试是编写高质量单元测试的重要组成部分,它们确保你的代码能够正确处理各种极端情况和异常输入,提高代码的健壮性和可靠性。
测试边界情况
1 | // tests/Unit/Services/MathServiceTest.php |
测试异常处理
异常处理是编写健壮代码的重要组成部分,测试异常处理确保你的代码能够正确捕获和处理各种异常情况,提高应用的可靠性和用户体验。
1 | // tests/Unit/Repositories/UserRepositoryTest.php |
4. 集成测试
集成测试验证多个组件之间的交互,确保它们能够协同工作。这是连接单元测试和端到端测试的重要桥梁。
4.1 测试控制器
基本控制器测试
1 | // tests/Feature/Controllers/UserControllerTest.php |
测试表单验证
1 | // tests/Feature/Controllers/AuthControllerTest.php |
4.2 测试服务与数据库交互
集成测试的重要组成部分是测试服务与数据库的交互,确保业务逻辑能够正确地与数据库进行通信,并且数据能够按照预期进行存储和检索。
测试服务与数据库
1 | // tests/Feature/Services/OrderServiceTest.php |
'user_id' => $user->id,
'items' => [
['product_id' => $product1->id, 'quantity' => 2],
['product_id' => $product2->id, 'quantity' => 1],
],
];
// 执行
$order = $orderService->createOrder($orderData);
// 断言
expect($order)->toBeInstanceOf(Order::class);
expect($order->user_id)->toBe($user->id);
expect($order->total)->toBe(400); // 2*100 + 1*200
// 验证订单项目
$this->assertDatabaseHas('order_items', [
'order_id' => $order->id,
'product_id' => $product1->id,
'quantity' => 2,
'price' => 100,
]);
$this->assertDatabaseHas('order_items', [
'order_id' => $order->id,
'product_id' => $product2->id,
'quantity' => 1,
'price' => 200,
]);
// 验证库存减少
$this->assertDatabaseHas('products', [
'id' => $product1->id,
'stock' => $product1->stock - 2,
]);
$this->assertDatabaseHas('products', [
'id' => $product2->id,
'stock' => $product2->stock - 1,
]);
});
test('cannot create order with insufficient stock', function () use (&$orderService) {
// 准备 - 创建库存为 1 的产品
$user = User::factory()->create();
$product = Product::factory()->create(['price' => 100, 'stock' => 1]);
$orderData = [
'user_id' => $user->id,
'items' => [
['product_id' => $product->id, 'quantity' => 2], // 尝试购买 2 个,但库存只有 1 个
],
];
// 执行 & 断言
$this->expectException(\App\Exceptions\InsufficientStockException::class);
$this->expectExceptionMessage('Insufficient stock for product: ' . $product->name);
$orderService->createOrder($orderData);
// 验证未创建订单
$this->assertDatabaseCount('orders', 0);
});
});
1 |
|
测试权限中间件
1 | // tests/Feature/Middleware/PermissionMiddlewareTest.php |
4.4 测试事件与监听器
测试事件触发
1 | // tests/Feature/Events/OrderPlacedEventTest.php |
5. API 测试
API 测试验证应用程序的接口是否按预期工作,确保与客户端的交互正常。
5.1 测试 RESTful API
基本 API 测试
1 | // tests/Feature/Api/UserApiTest.php |
测试资源 API
1 | // tests/Feature/Api/ProductApiTest.php |
5.2 测试 API 认证
测试 API 登录
1 | // tests/Feature/Api/AuthApiTest.php |
5.3 测试 API 错误处理
测试错误响应
1 | // tests/Feature/Api/ErrorHandlingTest.php |
6. 浏览器测试
浏览器测试使用 Laravel Dusk 模拟用户在浏览器中的操作,验证完整的用户流程。
6.1 配置 Dusk
安装与配置
1 | # 安装 Dusk |
配置测试环境
1 | // .env.dusk.local |
6.2 编写浏览器测试
测试认证流程
1 | // tests/Browser/AuthTest.php |
测试表单提交
1 | // tests/Browser/ProductTest.php |
7. 测试最佳实践
7.1 测试组织
测试目录结构
1 | tests/ |
7.2 测试命名约定
测试方法命名
- 描述性命名: 测试方法应该清晰描述测试的内容
- 使用动词: 描述测试的行为
- 具体场景: 包含具体的测试场景
示例:
test_user_can_register_with_valid_datatest_user_cannot_register_with_duplicate_emailtest_product_service_can_create_producttest_api_returns_404_for_non_existent_resource
7.3 测试编写技巧
测试准备与清理
1 | // 好的测试结构 |
使用测试辅助函数
1 | // tests/Pest.php |
7.4 测试性能优化
并行测试
1 | # 运行并行测试 |
测试数据库优化
1 | // 使用内存数据库进行测试 |
测试缓存
1 | // 缓存测试结果 |
7.5 持续集成测试
GitHub Actions 配置
1 | # .github/workflows/tests.yml |
GitLab CI 配置
1 | # .gitlab-ci.yml |
8. 测试覆盖率
8.1 配置代码覆盖率
Xdebug 配置
1 | ; php.ini |
运行覆盖率测试
1 | # 运行测试并生成覆盖率报告 |
8.2 覆盖率指标
关键覆盖率指标
| 指标 | 描述 | 目标值 |
|---|---|---|
| 行覆盖率 | 测试执行的代码行数百分比 | ≥ 80% |
| 分支覆盖率 | 测试执行的代码分支百分比 | ≥ 70% |
| 路径覆盖率 | 测试执行的代码路径百分比 | ≥ 60% |
| 方法覆盖率 | 测试覆盖的方法百分比 | ≥ 85% |
覆盖率分析
1 | # 查看覆盖率摘要 |
8.3 提高覆盖率的策略
优先测试关键组件
- 核心业务逻辑: 优先测试业务核心功能
- API 接口: 确保所有 API 端点都有测试
- 认证与授权: 测试所有认证和授权场景
- 数据处理: 测试数据验证和处理逻辑
- 错误处理: 测试各种错误场景
测试边界情况
- 输入边界: 测试最小值、最大值、空值等
- 业务规则边界: 测试业务规则的边界条件
- 异常情况: 测试各种异常场景
- 性能边界: 测试系统在边界负载下的表现
9. 高级测试技术
9.1 测试驱动开发 (TDD)
TDD 工作流程
- 编写失败的测试: 首先编写一个失败的测试,描述期望的行为
- 编写最小化代码: 编写足够的代码使测试通过
- 重构代码: 优化代码结构,保持测试通过
- 重复循环: 对每个功能重复上述步骤
TDD 示例
1 | // 1. 编写失败的测试 |
9.2 行为驱动开发 (BDD)
BDD 工作流程
- 定义行为: 使用自然语言描述功能行为
- 编写场景: 创建具体的测试场景
- 实现功能: 实现功能使场景通过
- 验证行为: 确保所有场景都通过
BDD 示例
1 | // 使用 Pest 的描述性语法 |
9.3 契约测试
消费者驱动契约测试
1 | // 消费者测试 |
9.4 性能测试
基本性能测试
1 | // tests/Feature/PerformanceTest.php |
10. 测试工具与集成
10.1 常用测试工具
核心测试工具
| 工具 | 用途 | 版本 |
|---|---|---|
| Pest | PHP 测试框架 | v3.0+ |
| PHPUnit | PHP 单元测试框架 | v10.0+ |
| Laravel Dusk | 浏览器测试 | v7.0+ |
| Mockery | 模拟库 | v1.6+ |
| Faker | 测试数据生成 | v1.23+ |
辅助测试工具
| 工具 | 用途 | 版本 |
|---|---|---|
| Xdebug | 代码覆盖率分析 | v3.2+ |
| PHPStan | 静态代码分析 | v1.10+ |
| Psalm | 静态代码分析 | v5.15+ |
| Codeception | 全栈测试框架 | v5.0+ |
| Behat | BDD 测试框架 | v3.13+ |
10.2 IDE 集成
PHPStorm 测试集成
配置测试框架:
- 打开
Settings > PHP > Test Frameworks - 配置 Pest 和 PHPUnit
- 打开
运行测试:
- 右键点击测试文件或方法
- 选择
Run 'TestName'
测试覆盖率:
- 运行测试时选择
Run with Coverage - 查看代码覆盖率高亮
- 运行测试时选择
VS Code 测试集成
安装扩展:
pestphp/pest-vscode- Pest 测试扩展recca0120/vscode-phpunit- PHPUnit 测试扩展
配置:
- 在
settings.json中配置测试路径
- 在
运行测试:
- 使用命令面板:
Pest: Run Test - 查看测试结果和覆盖率
- 使用命令面板:
10.3 测试报告集成
生成测试报告
1 | # 生成 JUnit XML 报告 |
CI/CD 集成
1 | # GitHub Actions 完整配置 |
11. 总结
Laravel 12 提供了强大的测试工具和框架,使开发者能够编写高质量、可维护的测试。通过遵循本文档中的最佳实践和技术指南,您可以:
- 建立完整的测试体系: 从单元测试到端到端测试,覆盖所有测试层次
- 提高代码质量: 通过测试发现和修复潜在问题
- 加速开发流程: 减少手动测试时间,提高开发效率
- 增强系统稳定性: 确保代码变更不会破坏现有功能
- 提升团队协作: 测试作为文档,帮助团队理解代码行为
采用测试驱动开发和持续集成实践,将使您的 Laravel 应用更加健壮、可靠,并为用户提供更好的体验。
// 准备
User::factory()->count(3)->create();
$user = User::factory()->create([‘role’ => ‘admin’]);
// 执行
$response = $this->actingAs($user)->getJson('/api/users');
// 断言
$response->assertStatus(200);
$response->assertJsonCount(4, 'data');
});
test('can get single user', function () {
// 准备
$user = User::factory()->create();
$admin = User::factory()->create(['role' => 'admin']);
// 执行
$response = $this->actingAs($admin)->getJson("/api/users/{$user->id}");
// 断言
$response->assertStatus(200);
$response->assertJson([
'data' => [
'id' => $user->id,
'name' => $user->name,
'email' => $user->email,
],
]);
});
});
1 |
|
5.2 API 认证测试
测试认证中间件
1 | test('unauthorized user cannot access protected API', function () { |
测试 API 速率限制
1 | test('API has rate limit', function () { |
6. 浏览器测试
Laravel Dusk 提供了强大的浏览器测试功能,可以测试前端交互和 JavaScript 功能。
6.1 安装与配置
安装 Laravel Dusk
1 | composer require laravel/dusk --dev |
配置 Dusk
1 | // .env.dusk.local |
6.2 编写浏览器测试
测试登录流程
1 | // tests/Browser/LoginTest.php |
测试表单提交
1 | test('user can register', function () { |
7. 测试套件的组织
7.1 目录结构
1 | tests/ |
7.2 测试分类
按功能分类
1 | tests/ |
按模块分类
1 | tests/ |
8. 测试覆盖率分析
8.1 配置代码覆盖率
安装 Xdebug
1 | # 安装 Xdebug |
配置 PHPUnit
1 | <!-- phpunit.xml --> |
8.2 生成覆盖率报告
使用 Pest 生成覆盖率报告
1 | # 生成 HTML 覆盖率报告 |
分析覆盖率报告
覆盖率报告通常包括以下指标:
- 行覆盖率:测试覆盖的代码行数百分比
- 分支覆盖率:测试覆盖的代码分支百分比
- 路径覆盖率:测试覆盖的代码路径百分比
- 函数覆盖率:测试覆盖的函数百分比
8.3 提高测试覆盖率
识别未覆盖的代码
1 | # 显示未覆盖的代码 |
优先测试核心功能
- 业务逻辑:优先测试核心业务逻辑
- 边界情况:测试边界条件和异常情况
- 关键路径:测试用户常用的功能路径
- 易错代码:测试历史上容易出错的代码
9. CI/CD 中的测试自动化
9.1 GitHub Actions 配置
基本配置
1 | # .github/workflows/run-tests.yml |
多环境测试
1 | # .github/workflows/run-tests.yml |
9.2 GitLab CI 配置
1 | # .gitlab-ci.yml |
10. 测试最佳实践
10.1 编写高质量测试
- 测试名称:使用描述性的测试名称
- 测试结构:遵循 Arrange-Act-Assert 模式
- 测试隔离:每个测试应该独立运行
- 测试速度:保持测试快速运行
- 测试维护:保持测试代码的整洁和可维护
10.2 测试原则
FIRST 原则:
- Fast:测试应该快速运行
- Independent:测试应该相互独立
- Repeatable:测试应该可重复运行
- Self-validating:测试应该自动验证结果
- Timely:测试应该及时编写
测试金字塔:
- 底部:大量的单元测试
- 中间:适量的集成测试
- 顶部:少量的端到端测试
10.3 常见测试陷阱
- 测试实现细节:避免测试实现细节,应该测试行为
- 过度模拟:不要过度使用 Mock,应该测试真实的交互
- 测试环境依赖:避免测试依赖外部服务
- 测试速度慢:避免测试中使用真实的数据库和网络请求
- 测试覆盖率迷恋:不要只追求覆盖率,应该关注测试质量
11. 实战案例:构建完整的测试套件
11.1 项目背景
- 规模:中型 e-commerce 应用
- 功能:产品管理、用户管理、购物车、支付
- 要求:测试覆盖率 > 80%
11.2 测试策略设计
1. 测试分层
单元测试:70%
- 服务层测试
- 工具类测试
- 模型测试
集成测试:20%
- 控制器测试
- API 测试
- 服务集成测试
端到端测试:10%
- 关键用户流程
- 支付流程
- 管理员功能
2. 测试重点
- 核心业务逻辑:产品管理、购物车、支付
- 用户流程:注册、登录、购买
- API 接口:RESTful API
- 边界情况:库存不足、支付失败
3. 测试实现
1 | // 产品服务测试 |
11.3 测试效果
| 指标 | 实现前 | 实现后 | 提升 |
|---|---|---|---|
| 测试覆盖率 | 0% | 85% | 85% |
| 代码质量 | 中等 | 高 | 显著 |
| 缺陷率 | 10% | 2% | 80% |
| 开发速度 | 慢 | 快 | 显著 |
| 维护成本 | 高 | 低 | 显著 |
12. 总结
Laravel 12 的测试体系提供了从单元测试到端到端测试的完整支持,结合 Pest v3 的优雅语法,为开发者构建高质量应用提供了强大的工具。
通过本文的介绍,开发者可以快速掌握 Laravel 12 的测试能力,构建一个完整、高效的测试套件。测试不仅可以保证代码质量,还可以提高开发效率,减少生产环境的 bug。
在实际项目中,应该根据项目的规模和复杂度,选择合适的测试策略,平衡测试的深度和广度。同时,应该将测试作为开发流程的一部分,持续编写和维护测试代码。
随着 Laravel 生态系统的不断发展,测试工具和实践也在不断演进。开发者应该保持关注 Laravel 的更新,及时采用新的测试技术和工具,为构建更好的 Laravel 应用而努力。



