最近我對自動化測試愈來愈感興趣 —— 密切關注着 PHPUnit,TDD,Laravel Dusk,Travis 以及其餘測試相關的關鍵詞,因此我決定看看周圍其餘人是如何作自動化測試的。我在 GitHub 上找到了至關多的 Laravel 開源項目,從裏面挑選出了 6 個來查看他們的測試方案。讓咱們分別看一下。php
免責聲明: 我只是查看了完整的基於 Laravel 5.3+ 的 Laravel 項目(不包括依賴包)ios
URL: https://github.com/laravelio/...laravel
最近從新啓動的 Laravel.io 已經將代碼在 GitHub 上開源。Dries Vints 在這個項目中寫的測試很是好。git
Laravel.io 使用功能測試 (Feature testing) 和組件測試 (Component testing)(和單元測試差很少)。有趣的是,在這兩種測試中都進行了相同或類似的測試。github
例子 1 -- tests/Feature/ReplyTest.phpweb
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.php設計模式
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。 這沒有什麼問題,僅僅是一個提醒。ide
這個項目也使用了 Travis 進行持續集成, 後來我發現大多數項目都使用了它。post
URL: https://github.com/cachethq/C...
在 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。同時這段邏輯是全部的測試 —— 一些抽象的 "魔術" 正在執行全部的工做。
我不是說這是壞事 —— 十分肯定他在內在的東西里工做的很好。他只是不容易先學習和遵循。但若是有人想深刻研究 —— 祝好運!
URL: https://github.com/octobercms...
市場上第一款基於 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 文件提到了設置文檔。
URL: https://github.com/orgmanager...
這是 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 命令並斷言其輸出 —— 很是有趣。我肯定他有效,但這是非標準的方式。
URL: https://github.com/PHPMap/phpmap
由 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'); }); }
URL: https://github.com/timegridio...
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 應用中最重要的功能之一。
在看過全部這些不一樣的項目以後(以及因爲各類緣由未說起的),如下是我對本身關於測試的主要要求:
以上是個人經驗,有沒有你要添加到開源項目列表中來學習測試的內容?
文章轉自: https://learnku.com/laravel/t...
更多文章: https://learnku.com/laravel/c...