免责声明: 我只是查看了完整的基于 Laravel 5.3+ 的 Laravel 项目(不包括依赖包)php
URL: github.com/laravelio/p…ios
最近从新启动的 Laravel.io 已经将代码在 GitHub 上开源。Dries Vints 在这个项目中写的测试很是好。laravel
Laravel.io 使用功能测试 (Feature testing) 和组件测试 (Component testing)(和单元测试差很少)。有趣的是,在这两种测试中都进行了相同或类似的测试。git
例子 1 -- tests/Feature/ReplyTest.phpgithub
public function users_can_add_a_reply_to_a_thread()
{
factory(Thread::class)->create(['subject' => 'The first thread', 'slug' => 'the-first-thread']);
$this->login();
$this->visit('/forum/the-first-thread')
->type('The first reply', 'body')
->press('Reply')
->see('The first thread')
->see('The first reply')
->see('Reply successfully added!');
}
复制代码
例子 2 -- tests/Components/Jobs/CreateReplyTest.phpweb
public function we_can_create_a_reply()
{
$job = new CreateReply('Foo', '', $this->createUser(), factory(Thread::class)->create());
$this->assertInstanceOf(Reply::class, $job->handle());
}
复制代码
这样作很好: 同时测试 Jobs 层和实际在浏览器中点击一些东西。设计模式
我还注意到 Laravel.io 已经升级到了 Laravel 5.4, 可是测试套件仍然使用的是5.3的风格, 使用 BrowserKitTestCase implementation。 这没有什么问题,仅仅是一个提醒。浏览器
这个项目也使用了 Travis 进行持续集成, 后来我发现大多数项目都使用了它。ide
URL: github.com/cachethq/Ca…post
在 James Brooks 和 Graham Campbell 的带领下,这个项目有一个庞大的测试组件。他甚至经过观察表层很难理解。
因此,咱们从哪里开始... 事实上,我甚至不会深度燕郊这个项目的测试逻辑, 由于他太难理解了,这是一个例子 —— tests/Models/ComponentTest.php:
use AltThree\TestBench\ValidationTrait;
use CachetHQ\Cachet\Models\Component;
use CachetHQ\Tests\Cachet\AbstractTestCase;
class ComponentTest extends AbstractTestCase
{
use ValidationTrait;
public function testValidation()
{
$this->checkRules(new Component());
}
}
复制代码
好吧,这里用到了 ValidationTrait,而后是一些 AbstractTestCase。同时这段逻辑是全部的测试 —— 一些抽象的 "魔术" 正在执行全部的工做。
我不是说这是坏事 —— 十分肯定他在内在的东西里工做的很好。他只是不容易先学习和遵循。但若是有人想深刻研究 —— 祝好运!
市场上第一款基于 Laravel 的 CMS,他拥有很是不错的测试组件。
首先 -—— tests 文件夹有一个 真正信息详实的 readme.md 文件,专门用于测试过程。
October CMS 的全部测试包括:
每一个 "区域" 都有对应的基类来扩展 —— 有 TestCase,UiTestCase 和 PluginTestCase。
逻辑也很是复杂和抽象 —— 这里有一个例子 tests/unit/backend/models/ExportModelTest.php:
class ExportModelTest extends TestCase
{
//
// 辅助
//
protected static function callProtectedMethod($object, $name, $params = [])
{
$className = get_class($object);
$class = new ReflectionClass($className);
$method = $class->getMethod($name);
$method->setAccessible(true);
return $method->invokeArgs($object, $params);
}
//
// 测试
//
public function testEncodeArrayValue()
{
$model = new ExampleExportModel;
$data = ['foo', 'bar'];
$result = self::callProtectedMethod($model, 'encodeArrayValue', [$data]);
$this->assertEquals('foo|bar', $result);
$data = ['dps | heals | tank', 'paladin', 'berserker', 'gunner'];
$result = self::callProtectedMethod($model, 'encodeArrayValue', [$data]);
$this->assertEquals('dps \| heals \| tank|paladin|berserker|gunner', $result);
$data = ['art direction', 'roman empire', 'sci-fi'];
$result = self::callProtectedMethod($model, 'encodeArrayValue', [$data, '-']);
$this->assertEquals('art direction-roman empire-sci\-fi', $result);
}
}
复制代码
如你所见,这里有一个静态辅助方法(顺便说一下,在其余类中重复使用),而后获取类/方法并调用他啊, 我确信做者能当即理解逻辑,但这对外人来讲很困难。
一样有趣的是,OctoberCMS 使用 Selenium 来获取一些功能:tests/readme.md 文件提到了设置文档。
这是 Miguel Piedrafita 的一个很是简单的项目,Orgmanager 的测试也是很是简单易懂的。还分为单元,功能和 API 测试。
我在这里看到一个有趣的示例 —— 从测试中调用 Artisan 命令,例如 unit/JoinTest.php:
public function testJoinCommand()
{
$user = factory(User::class)->create();
$org = factory(Org::class)->create([
'userid' => $user->id,
]);
Github::shouldReceive('authenticate')
->once()
->with($org->user->token, null, 'http_token')
->andReturn();
Artisan::call('orgmanager:joinorg', [
'org' => $org->id,
'username' => $user->github_username,
]);
$this->assertEquals($user->github_username.' was invited to '.$org->name."\n", Artisan::output());
}
复制代码
调用 artisan 命令并断言其输出 —— 很是有趣。我肯定他有效,但这是非标准的方式。
由 Florian Wartner 建立及维护。
PHPMap 有一个测试组件,令人联想到 Laracasts 或 测试驱动 Laravel 课程 讲述的标准。这是 Feature/FavoritesTest.php 的例子。
public function guests_can_not_favorite_anything()
{
$this->withExceptionHandling()
->post('forum/replies/1/favorites')
->assertRedirect('/login');
}
public function an_authenticated_user_can_favorite_any_reply()
{
$this->signIn();
$reply = create('App\Models\Forum\Reply');
$this->post('forum/replies/'.$reply->id.'/forum/favorites');
$this->assertCount(1, $reply->favorites);
}
复制代码
PHPMap 的测试分为单元,功能及 Laravel Dusk 等等!最后我发现了一个真正在生产环境使用 Dusk 的项目。这是他的门面 —— tests/Browser/MapTest.php:
public function testMap()
{
$this->browse(function ($browser) {
$browser->visit('/map')
->assertSee('PHPMap');
});
}
复制代码
Timegrid 的最大贡献者是 Ariel Vallese,同时他在测试方面作了很是好的工做。
这里只有不少的测试: 单元,验收和集成,每一个文件都有更深的子文件夹目录,例如:—— acceptance/scenarios/consulting/ConsultingScenarioTest.php:
public function it_fits_for_consulting_scenario()
{
$this->arrangeScenario();
$this->the_business_publishes_a_consulting_service();
$this->the_business_publishes_vacancies();
$this->a_user_subscribes_to_business();
$this->the_user_queries_vacancies();
$this->it_provides_available_times_for_requested_service_date();
$this->the_user_takes_a_reservation();
$this->the_user_sees_the_reservation_ticket();
}
public function the_business_publishes_a_consulting_service()
{
$this->service = $this->makeService([
'name' => 'OnSite 4hs Support',
'duration' => 60 * 4,
]);
$this->actingAs($this->owner);
$this->call('POST', route('manager.business.service.store', $this->business), $this->service->toArray());
$this->assertCount(1, $this->business->fresh()->services);
}
复制代码
一个一体化的方法,以后是一个个列举更多的测试:
仓库中的官方统计数据看起来很是好: 89% 的测试覆盖率。
最后,有趣的是,做者甚至测试了迁移文件,如 tests/unit/migration/MigrationTest.php:
public function it_refreshes_rollbacks_and_seeds_the_database()
{
$database = env('DB_CONNECTION');
$this->assertNotNull($database);
$exitCode = Artisan::call('migrate:refresh', ['--database' => $database]);
$this->assertEquals(0, $exitCode);
$exitCode = Artisan::call('migrate:rollback', ['--database' => $database]);
$this->assertEquals(0, $exitCode);
$exitCode = Artisan::call('migrate', ['--database' => $database]);
$this->assertEquals(0, $exitCode);
$exitCode = Artisan::call('db:seed', ['--database' => $database]);
$this->assertEquals(0, $exitCode);
}
复制代码
在测试中使用 Artisan 命令或许不是最佳的设计模式,但他只是测试任何 web 应用中最重要的功能之一。
在看过全部这些不一样的项目以后(以及因为各类缘由未说起的),如下是我对本身关于测试的主要要求:
以上是个人经验,有没有你要添加到开源项目列表中来学习测试的内容?