codecamp

Laravel 项目开发规范 Testing 规范

渐进式测试

100% 的测试覆盖率,需要花费在测试代码上的工时,丝毫不亚于业务代码的开发时间。

如开发 Deadline 不允许,做不到 100% 测试覆盖率,应该考虑对程序入口进行测试。这种方式的时间利用比最高。

Laravel 项目中程序入口,一般有以下四种:

  • Web —— 程序的网页模块;
  • API —— 程序的 API 模块;
  • Admin —— 管理员后台页面;
  • Job —— 队列任务;
  • Command —— 自定义的 Artisan 命令行。

对这些入口进行 100% 的测试覆盖,可以很大范围内测试到项目代码。

测试速度

编写测试时,必须永远把执行速度放在首位。

单元测试

所有的单元测试,都必须放置于 tests/Unit 目录下。且必须使用子目录存储,绝不直接放置于此目录下。

集成测试

所有的集成测试,都必须放置于 tests/Feature 目录下。且必须使用子目录存储,绝不直接放置于此目录下。

常见的子目录按照入口,应该划分如下:

├── API
├── Web
├── Admin
├── Command
└── Job

Fixture 数据

测试中使用到样例数据,必须放置于 tests/Fixtures 目录中。且必须使用子目录存储,绝不直接放置于此目录下。

运行多个环境

测试代码必须在开发同事的机器上能运行,测试必须在 Beta 环境下能运行。

并发测试

所有的测试,都 必须 支持并发测试,这样可以极大节省 CI 中测试运行的时间,提高整个工作流的速度。

每次提交代码前,使用以下命令跑一下不报错即可:

php artisan test -p

支持并发测试:

composer require brianium/paratest

用例测试而不是代码测试

写 Feature Test 的时候,必须使用用例测试(User Story),而不是代码测试。

❌代码测试的例子:

// tests/Feature/API/V1/UserAddressControllerTest.php

class UserAddressControllerTest extends APITest
{
    public function test_controller_index_method()
    {
    }

    public function test_controller_create_method()
    {
    }
}

✅ 用例测试:

// tests/Feature/API/V1/UserAddressControllerTest.php

class UserAddressControllerTest extends APITest
{
    public function test_user_can_view_user_address_index()
    {
    }

    public function test_guest_can_not_create_user_address()
    {
    }

    public function test_user_can_create_user_address()
    {
    }
}

绝不测试第三方服务

程序中经常会使用第三方服务,例如发送邮件使用 SendCloud 的 API 、或发送短信 API。

将这些服务 API 调用封装到 Service 层,编写测试代码时,对其进行 Mock 。

建议:检测测试代码是否使用第三方服务,最好的方法就是把 Wifi 关掉,然后跑一遍测试。如果有错误发生,证明调用了第三方 API。


Laravel 项目开发规范 Service 模式
Laravel 项目开发规范 模型规范
温馨提示
下载编程狮App,免费阅读超1000+编程语言教程
取消
确定
目录

关闭

MIP.setData({ 'pageTheme' : getCookie('pageTheme') || {'day':true, 'night':false}, 'pageFontSize' : getCookie('pageFontSize') || 20 }); MIP.watch('pageTheme', function(newValue){ setCookie('pageTheme', JSON.stringify(newValue)) }); MIP.watch('pageFontSize', function(newValue){ setCookie('pageFontSize', newValue) }); function setCookie(name, value){ var days = 1; var exp = new Date(); exp.setTime(exp.getTime() + days*24*60*60*1000); document.cookie = name + '=' + value + ';expires=' + exp.toUTCString(); } function getCookie(name){ var reg = new RegExp('(^| )' + name + '=([^;]*)(;|$)'); return document.cookie.match(reg) ? JSON.parse(document.cookie.match(reg)[2]) : null; }