原文地址: Laravel 5.1 Beauty - Testingjavascript
Note 本系列第四節內容.php
本章會建立一個之後能夠用到的項目便於之後咱們的課程使用, 同時也會查課各類測試選項. 之後一段時間內會開發一個 Markdown 文本轉換成 Html 的服務信息.css
根據以前的章節 Six Steps to Starting a New Laravel 5.1 Project 建立 l5beauty 項目下面所示項目java
首先在你的系統安裝 app 框架node
$ laravel new l5beauty Crafting application... Generating optimized class loader Compiling common classes Application key [rzUhyDksVxzTXFjzFYiOWToqpunI2m6X] set successfully. Application ready! Build something amazing.
接下來設置 l5beauty.app
做爲虛擬主機.mysql
$ serve l5beauty.app ~/l5beauty/public dos2unix: converting file /vagrant/scripts/serve.sh to Unix format ... * Restarting nginx nginx [ OK ] php5-fpm stop/waiting php5-fpm start/running, process 2169
回到主機, 添加如下記錄到映射文件nginx
192.168.10.10 l5beauty.app
從主機中, 按照如下步驟安裝 NPM 本地包laravel
$ cd l5beauty $ npm install | > node-sass@2.0.1 install /Users/chuck/Code/l5beauty/node_modules/laravel-\ elixir/node_modules/gulp-sass/node_modules/node-sass > node scripts/install.js > node-sass@2.0.1 postinstall /Users/chuck/Code/l5beauty/node_modules/\ laravel-elixir/node_modules/gulp-sass/node_modules/node-sass > node scripts/build.js `darwin-x64-node-0.10` exists; testing Binary is fine; exiting gulp@3.8.11 node_modules/gulp ├── v8flags@2.0.2 ├── pretty-hrtime@0.2.2 [snip]
回到主機, 建立數據庫git
$ mysql --user=homestead --password=secret mysql> create database l5beauty; Query OK, 1 row affected (0.00 sec) mysql> exit; Bye
編輯 .env
文件, 修改數據庫爲 l5beauty
.github
// Change the following line DB_DATABASE=homestead // To the correct value DB_DATABASE=l5beauty
最後, 訪問 http://l5beauty.app
, 確保一切可用.
Figure 6.1 - Step 5 - 在瀏覽器中測試
Laravel 5.1 已經準備好測試了, 有個最簡單的方式來檢測一個訪問是否返回200響應.
運行 PHPUnit , 簡單的在根目錄上執行 phpunit
就OK
$ cd l5beauty ~/l5beauty $ phpunit PHPUnit 4.7.4 by Sebastian Bergmann and contributors. Time: 544 ms, Memory: 10.25Mb OK (1 test, 2 assertions)
若是你在運行 phpunit
收到 command not found 或者 permissions denied 錯誤提示, 有多是由於安裝問題. phpunit
命令通常會存放在 vendor/bin
目錄而且添加進系統變量, 問題是 Laravel 命令有一個bug是沒有給這個命令設置相應的權限
使用以下方法解決這個問題:
Step 1 - 刪除 vendor
目錄
Step 2 - 在代碼根目錄使用 composer update
命令從新建立 vendor
目錄. (操做系統中運行)
這樣, 而後從新執行 phpunit
在 Laravel 5.1 項目根目錄中有個文件 phpunit.xml
. 這個文件包含使用 phpunit
運行時候的配置
phpunit.xml
的測試會放置在 tests
目錄, 這裏有兩個文件
ExampleTest.php
- 包含一個測試方法 testBasicExample()
. 這個 ExampleTest
類集成自 TestCase
類.TestCase.php
- Laravel 基礎測試單元.查看 testBasicExample()
方法 ExampleTest.php
.
public function testBasicExample() { $this->visit('/') ->see('Laravel 5'); }
這個測試告訴咱們 "訪問主頁而且可以看到內容 ‘Laravel 5’", 還能比這個更簡潔麼 ?
TestCase
類提供在框架中的應用方法和屬性. TestCase
一樣提供了一個附加斷言列表方法和 crawler 類型測試
Crawler 容許你測試web應用. 這些方法都有個統一的優勢就是都可以返回 $this
, 容許你建立 ->visit()->see()
相似這樣的鏈式調用.
下邊是一些屬性和方法:
$this->response
web應用返回的最後的響應
$this->currentUri
當前查看的Uri
visit($uri)
(Fluent) 使用 get 方法訪問給定的uri
get($uri, array $headers = [])
(Fluent) 使用 get 方法訪問url, 並能夠傳輸給定的header
post($uri, array $data = [], array $headers = [])
(Fluent) post 請求
put($uri, array $data = [], array $headers = [])
(Fluent) put 請求
patch($uri, array $data = [], array $headers = [])
(Fluent) PATCH 請求
delete($uri, array $data = [], array $headers = [])
(Fluent) DELETE 請求
followRedirects()
(Fluent) 跟蹤最近返回的重定向
see($text, $negate = false)
(Fluent) 查找頁面上顯示的內容/顯示/不顯示
seeJson(array $data = null)
(Fluent) 斷定請求包含 json, 若是傳輸了 $data
參數, json 值必須匹配.
seeStatusCode($status)
(Fluent) 相應是否返回指定的狀態碼
seePageIs($uri)
(Fluent) 當前頁面是不是指定的URI
seeOnPage($uri)
and landOn($uri)
(Fluent) Alias seePageIs()
click($name)
(Fluent) 經過name 或者 id 來請求點擊
type($text, $element)
(Fluent) 填充自定義的文本
check($element)
(Fluent) 檢測頁面的checkbox
select($option, $element)
(Fluent) 選擇下拉項
attach($absolutePath, $element)
(Fluent) 附件
press($buttonText)
(Fluent) 提交指定文本的text
withoutMiddleware()
(Fluent) 禁用 middleware
dump()
輸入最近返回的內容
這裏有額外的 Laravel 5.1 方法和屬性
$app
$app 實例
$code
artisan 返回的最近的 code 碼
refreshApplication()
刷新應用, setup()方法會自動調用這個方法.
call($method, $uri, $parameters = [], $cookies = [], $files = [], $server = [], $content = null)
調用指定的url 而且返回響應.
callSecure($method, $uri, $parameters = [], $cookies = [], $files = [], $server = [], $content = null)
調用 https 訪問url而且返回響應
action($method, $action, $wildcards = [], $parameters = [], $cookies = [], $files = [], $server = [], $content = null)
調用控制器方法
route($method, $name, $routeParameters = [], $parameters = [], $cookies = [], $files = [], $server = [], $content = null)
調用路由而且返回方法.
instance($abstract, $object)
註冊對象的實例
expectsEvents($events)
指定可能被觸發的事件列表.
withoutEvents()
不調用事件
expectsJobs($jobs)
註冊隊列
withSession(array $data)
使用session
session(array $data)
開始並設置 session
flushSession()
刷新當前session 的內容
startSession()
開始 session
actingAs($user)
(Fluent) 設置當前登陸的用戶
be($user)
設置用戶
seeInDatabase($table, array $data, $connection = null)
(Fluent) 檢測給定的數據是否存在在數據庫中
notSeeInDatabase($table, $array $data, $connection = null)
(Fluent) 檢測數據是否不存在數據庫中
missingFromDatabase($table, array $data, $connection = null)
(Fluent) Alias notSeeInDatabase()
.
seed()
數據庫數據seed 生成器
artisan($command, $parameters = [])
指定 artisan 命令而且返回代碼
上邊的方法/屬性都可以在 test 中 使用, 默認的 ExampleTest.php
中存在一個方法 testBasicExample()
, 這個調用了 $this->call(...)
方法.
除了標準的 PHPUnit 斷言(assertEquals()
, assertContains()
, assertInstanceOf()
, ...)以外, 還存在不少容許測試 web 應用的檢測項目
assertPageLoaded($uri, $message = null)
檢測最近的頁面是否被加載, 若是不存在 url / message 時候會報錯
assertResponseOk()
是否頁面相應OK
assertReponseStatus($code)
是否響應指定的code
assertViewHas($key, $value = null)
視圖中是否存在指定的數據
assertViewHasAll($bindings)
視圖中是否存在指定的一系列數據
assertViewMissing($key)
指定視圖中是否不存在這個數據
assertRedirectedTo($uri, $with = [])
檢測是否重定向到指定的uri
assertRedirectedToRoute($name, $parameters = [], $with = [])
是否客戶端重定向到指定的路由
assertRedirectedToAction($name, $parameters = [], $with = [])
是否重定向到 action
assertSessionHas($key, $value = null)
session 中是否存在 key/ value
assertSessionHasAll($bindings)
session 中是否存在指定的 kv
assertSessionHasErrors($bindings = [])
session 是否存在錯誤
assertHasOldInput()
session 中是否存在之前的數據
Gulp 是用javascript 寫成的編譯和自動化工具. 基本用來最小化源代碼或者從源代碼生成文件. Gulp 可以監控源代碼的改變而且自動運行指定的任務
Laravel 5.1 存在 Laravel Elixir 容許運行 gulp 任務. Elixir 加入了更簡潔的語法. 你這樣想 PHP 中的 Laravel, Gulp 中的 Elixir.
一個最經常使用的 Gulp 是自動化測試. 咱們根據 TDD (Test Driven Development) 來自動化運行咱們的測試任務.
首先, 編輯 gulpfile.js
文件, 並按照如下修改.
var elixir = require('laravel-elixir'); elixir(function(mix) { mix.phpUnit(); });
這裏咱們調用 elixir()
方法. 傳遞一個函數. 這個函數接收一個 mix 對象. 這個函數可以幹不少你可能想都想不到的事情. 你可能想經過 less 文件編譯 css 文件. 而後合併 css 文件, 而後再文件末尾加綴上版本號. 全部的這些事情均可以經過 mix
對象來運行.
可是如今, 咱們僅僅運行 PHPUnit 測試.
接下來, 直接運行 glup
~% cd Code/l5beauty ~/Code/l5beauty% gulp [15:26:23] Using gulpfile ~/Code/l5beauty/gulpfile.js [15:26:23] Starting 'default'... [15:26:23] Starting 'phpunit'... [15:26:25] Finished 'default' after 2.15 s [15:26:25] *** Debug Cmd: ./vendor/bin/phpunit --colors --debug *** [15:26:28] PHPUnit 4.7.4 by Sebastian Bergmann and contributors. Configuration read from /Users/chuck/Code/l5beauty/phpunit.xml Starting test 'ExampleTest::testBasicExample'. Time: 2.07 seconds, Memory: 10.25Mb OK (1 test, 2 assertions) [15:26:28] gulp-notify: [Green!] [15:26:28] Finished 'phpunit' after 4.96 s
你可能收到一個通知, 一個彈框, 綠色告知你全部測試都已經經過了
Figure 6.2 - Gulp’s PHPUnit Success on Windows 8.1
想要使用 gulp進行自動化測試, 運行 gulp tdd
~% cd Code/l5beauty ~/Code/l5beauty% gulp tdd [15:29:49] Using gulpfile ~/Code/l5beauty/gulpfile.js [15:29:49] Starting 'tdd'... [15:29:49] Finished 'tdd' after 21 ms
這個命令掛載在這裏, 監聽源文件的變化, 而且在須要的時候進行單元測試.
想要查看如何運行的. 讓咱們中段存在的單元測試.
改變 tests/ExampleTest.php
的 see()
方法.
->see('Laravel 5x');
當你保存這個文件, gulp 將會通知而且從新運行 PHPUnit , 這個將會執行錯誤. 而後你會看到一個紅色的錯誤提示
Figure 6.3 - Gulp’s PHPUnit Failure on Mac
若是你要從新更改回來,保存, 而後 gulp 會從新運行 PHPUnit, 而後你會看到綠色的圖標
按下 Ctrl+C
在博客應用中咱們會使用 Markdown 語法來寫文章, 若是你不熟悉 markdown, 能夠經過鏈接來檢查這個語法, 這是一個快速讀/寫而且可以保存爲 HTML.
舉例說明, 咱們會建立一個服務項目來生成HTML.
這裏有許多的PHP包來把markdown 轉換爲HTML, 若是你去 http://packagist.org
這裏搜索 markdown , 會發現 20 多頁的包.
咱們會使用 Michel Fortin 建立的包. 由於"好", 接下來咱們運行以下的命令來拉取這個包
~/Code/l5beauty% composer require michelf/php-markdown Using version ^1.5 for michelf/php-markdown ./composer.json has been updated Loading composer repositories with package information Updating dependencies (including require-dev) - Installing michelf/php-markdown (1.5.0) Downloading: 100% Writing lock file Generating autoload files Generating optimized class loader ~/Code/l5beauty% composer require "michelf/php-smartypants=1.6.0-beta1" ./composer.json has been updated Loading composer repositories with package information Updating dependencies (including require-dev) - Installing michelf/php-smartypants (1.6.0-beta1) Loading from cache Writing lock file Generating autoload files Generating optimized class loader
你有沒有注意到指定了包版本號. 這是由於寫這篇文章的時候尚未一個穩定的版本號可以自動拉取到
開始 TDD session 的第一件事就是開啓 TDD 模式
~/Code/l5beauty% gulp tdd [19:41:38] Using gulpfile ~/Code/l5beauty/gulpfile.js [19:41:38] Starting 'tdd'... [19:41:38] Finished 'tdd' after 23 ms
如今 gulp 監控 PHPUnit 的改變. 讓咱們建立測試類
在 tests
目錄, 建立一個新文件夾命名爲 Services
同時建立一個文件 MarkdownerTest.php
<?php class MarkdownerTest extends TestCase { # 保存 markdown 對象 protected $markdown; # 建立 Markdowner 對象 public function setup() { $this->markdown = new \App\Services\Markdowner(); } # 測試 public function testSimpleParagraph() { $this->assertEquals( "<p>test</p>\n", $this->markdown->toHTML('test') ); } }
這裏會報錯
即便告訴你檢測失敗, 日誌中也會存在相應的錯誤日誌, 這裏很明顯的是 App\Services\Markdowner
這個類不存在.
這裏咱們建立一個服務來封裝 php-markdown 和 php-smartypants 來加載導入的服務
在 app\Services
目錄建立一個 Markdowner.php
服務並填寫如下的內容 .
<?php # 命名空間 namespace App\Services; # 導入的類 use Michelf\MarkdownExtra; use Michelf\SmartyPants; class Markdowner { # 轉換類 public function toHTML($text) { $text = $this->preTransformText($text); $text = MarkdownExtra::defaultTransform($text); $text = SmartyPants::defaultTransform($text); $text = $this->postTransformText($text); return $text; } protected function preTransformText($text) { return $text; } protected function postTransformText($text) { return $text; } }
當你保存了這個文件, Gulp 應當顯示一個綠色的提示框. 告訴你執行OK.
若是你沒有收到綠色的提示. 檢測文件和測試類.
你們都贊成的是, 這不是一個好的 TDD 測試例子, 由於太簡單了. 實際的會有好多操做步驟和迭代, 以下
目前爲止, 全部的咱們 Markdowner
類在測試前都是不完整的.要在該類上進行 純 單元測試,應該將其結構化以便將 MarkdownExtra
和 SmartyPants
類的實例注入到構造函數中, 經過這種方式咱們的單元測試能夠注入模擬對象,而且只驗證 MarkdownExtra
的行爲,而不是它所調用的類.
但這不是一本關於測試的書。事實上,這是討論測試的唯一一章。咱們會離開這個結構,但須要再添加幾個測試。
更新 MarkdownerTest
來和下面的內容一致
<?php class MarkdownerTest extends TestCase { protected $markdown; public function setup() { $this->markdown = new \App\Services\Markdowner(); } /** * @dataProvider conversionsProvider */ public function testConversions($value, $expected) { $this->assertEquals($expected, $this->markdown->toHTML($value)); } public function conversionsProvider() { return [ ["test", "<p>test</p>\n"], ["# title", "<h1>title</h1>\n"], ["Here's Johnny!", "<p>Here’s Johnny!</p>\n"], ]; } }
在這裏,咱們更改了測試類用來一次測試多個轉換,並在 conversionsProvider()
中添加了三個測試。在進行下一步驟以前,你的測試結果應該是綠色的。
在系統控制檯中一旦測試是綠色的,按 Ctrl+C
來中止 Gulp
這裏並非想使用 Laravel 5.1
提供一個完整的測試方法,由於在PHP中沒有單獨的方法來進行測試。
所以,在 Laravel 5 5.1 中沒有單一的測試方法。
可是,咱們將探索一些替代方案
除了 PHPUnit ,Laravel 5.1 還提供了 phpspec 。這是另外一種流行的PHP測試,它更多地關注於 BDD(行爲驅動開發)
這裏有一些關於phpspec的註釋。
vendor/bin
, 所以你能夠在項目根目錄下調用 phpspec
.phpspec.yml
.phpSpec()
函數, 你能夠在 mix
對象中運行.App
改爲其餘的命名空間, 確保同步更新 phpspec.yml
中的配置.雖然 PHPUnit 是 PHP 單元測試的標準,但也有其餘的包可使用
這些測試真實的使用了您的應用程序,而不是僅僅驗證您的應用程序中的代碼單元。當使用流暢的測試方法 Laravel 5.1 時,你可使用 PHPUnit 進行一些功能測試. ExampleTest.php
提供了一個簡單的示例. 可是也有其餘的測試框架關注於功能/驗收測試(functional / acceptance testing).
BDD(行爲驅動開發)有兩種方式: SpecBDD 和 StoryBDD
SpecDD 關注代碼的技術方面。Laravel 5.1 包含了 _phpspec_, 這是SpecDD的標準
StoryBDD 強調業務或特性測試. Behat 是最流行的 StoryBDD 框架。一樣 Codeception 也能夠用於 StoryBDD 。
咱們在這一章所作的第一件事就是建立一個名爲 l5beauty 的項目。而後咱們在這個項目中使用 PHPUnit 進行單元測試。最後,咱們建立了一個 Markdowner
服務類,這有兩個目的 一是測試, 二是並在之後將 markdown 轉換爲 HTML 。
這是一個至關長的章節,由於測試是一個很大的話題,而一個章節沒法給出公正的評價。可是,正如我所提到的,測試並非本書的重點。在隨後的章節中,將再也不進行測試。
下一章咱們討論一些如何讓系統更快的話題如何?