基於 Laravel 開發博客應用系列 —— 從測試開始(二):使用Gulp實現自動化測試

三、使用 Gulp 進行 TDD(測試驅動開發)

Gulp 是一個使用 JavaScript 編寫的自動化構建工具。用於對前端通用任務(如最小化、壓縮、編譯)進行自動構建。Gulp 還能夠用來監控源代碼的改動並自動運行任務。php

Laravel 5.1 提供了一個封裝 Gulp 的 Laravel Elixir 包,可用於輕鬆構建 Gulp 任務,Elixir 爲 Gulp 添加了優雅的語法,Elixir 之於 Gulp 正如 Laravel 之於 PHP。前端

Gulp 最多見的用法之一就是自動構建單元測試,這裏咱們將遵循 TDD(測試驅動開發)流程讓 Gulp 自動運行測試。laravel

首先,編輯根目錄下的 gulpfile.js 文件以下:git

var elixir = require('laravel-elixir');

elixir(function(mix) {
    mix.phpUnit();
});

這裏咱們調用 elixir() 方法,接收的 mix 對象能夠用於處理不少事情。你能夠用它來將 LESS 文件編譯成 CSS 文件,也能夠用它來將多個 CSS 文件合併到一塊兒,而且爲合併後的文件添加版本控制,等等等等。全部這些事情均可以經過調用 mix 對象提供的接口方法來實現。github

可是如今,咱們只運行 PHPUnit 測試。web

接下來,在本地主機的項目根目錄下,運行 gulp 來看看會發生什麼:gulp

gulp運行phpunit執行結果

你應該還會接收到一個彈出框通知,通知若是是綠色的代表測試成功:ubuntu

2015-11-29 15-35-01

若是想讓 gulp 進入自動進行單元測試模式,須要在本地主機的命令行中使用 gulp tdd 命令:markdown

使用gulp tdd實現自動化測試

若是Ubuntu下執行該命令報錯:Error: watch ENOSPC,對應解決辦法是在終端執行以下命令:app

echo fs.inotify.max_user_watches=524288 | sudo tee -a /etc/sysctl.conf && sudo sysctl -p

再從新運行 gulp tdd 便可。

運行 gulp tdd 命令後該命令會一直掛起在那裏,監聽源文件的修改,並在須要的時候運行單元測試。

爲了演示是否有效,咱們修改 tests/ExampleTest.php 中的 see() 這一行測試代碼以下:

$this->visit('/')->see('Laravel Academy');

保存這個文件後,gulp 將會接到通知並再次運行單元測試。這一次運行測試失敗,並會看到相似下面這樣的失敗提示框:

使用Gulp運行單元測試失敗提示框

撤銷 tests/ExampleTest.php 中的修改並保存,gulp 會再次運行 PHPUnit,這一次又能夠接收到測試成功通知。

注:要退出 Gulp 的 tdd 模式只需使用快捷鍵 Ctrl+C 便可。

四、建立Markdown服務

在本博客項目中咱們將使用 Markdown 格式編輯文章。Markdown 是一種輕量級的標記語言,Markdown 的理念是能讓文檔更容易讀、寫和隨意改。Markdown 格式文本能夠被輕鬆轉化爲 HTML。

爲了舉例進行測試,咱們將要使用 TDD 開發流程構建將 Markdown 文本轉化爲 HTML 文本的服務。

安裝 Markdown 依賴包

有不少 PHP 包可用於將 Markdown 轉化爲 HTML。這裏咱們使用 Michel Fortin 提供的包 SmartyPants,在本地主機上使用 Composer 安裝下面兩個依賴包:

nonfu@ubuntu:~/Code/blog$ composer require michelf/php-markdown 
nonfu@ubuntu:~/Code/blog$ composer require "michelf/php-smartypants=1.6.0-beta1"

建立 Markdown 測試類

開啓 TDD 首先要作的事情就是觸發 gulp 爲 tdd 模式(若是已經開啓略過此步):

nonfu@ubuntu:~/Code/blog$ gulp tdd

如今 Gulp 已經在監聽文件修改,一旦有「風吹草動」,就會當即運行 PHPUnit。

下面咱們來建立測試類。在 tests 目錄中建立一個 Services 文件夾,並在該文件夾下新建一個MarkdownerTest.php,編輯文件內容以下:

<?php

class MarkdownerTest extends TestCase
{

    protected $markdown;

    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 這個類不存在。

建立Markdowner服務

這裏咱們建立一個封裝前面使用 Composer 安裝的 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 檢測到文件修改而後從新運行單元測試,此次會就收到綠色的提示,表明測試經過,一切正常。

若是沒有看到綠色提示,則表明測試失敗,須要回頭檢查下 App\Services\Markdowner 和 MarkdownerTest 這兩個類看是否有什麼問題。

更加複雜的迭代測試

誠然,這並非 TDD 的最佳示例,由於這只是先建立一個簡單的測試類,而後建立實現類修復測試出現的問題。在實際應用場景中,TDD 應該有更屢次的迭代,其大體流程應該像這樣:

  • 建立 MarkdownerTest,定義測試方法
  • 測試失敗
  • 建立 Markdowner 類,硬編碼 toHTML() 進行測試
  • 測試成功
  • 修改 Markdowner 類使用 MarkdownExtra
  • 測試成功
  • 添加 testQuotes() 方法到 MarkdownerTest 類
  • 測試失敗
  • 修改 Markdowner 類使用 SmartyPants
  • 測試成功

以此類推。甚至 Markdowner 類的結構都是有缺陷的,要對該類進行純正的單元測試,應該將 MarkdownExtra 和  SmartyPants 的實例注入到 Markdowner 的構造函數中,這樣的話咱們的單元測試能夠注入模擬的對象而且只驗證  MarkdownExtra 的行爲而不是其調用的類。

可是本系列教程不是關於測試的,實際上,咱們只會在這裏討論測試,咱們仍將保留其結構可是會添加更多的測試。

修改 MarkdownerTest.php 文件內容以下:

<?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&#8217;s Johnny!</p>\n"],
        ];
    }
}

這裏咱們修改測試類同時進行多個轉化測試。

五、其它測試方法

這裏咱們不想列出 Laravel 5.1 中全部可用的測試方法,由於PHP中的測試方法不是單一的,也不是固定不變的,在 Laravel 中一樣也是如此。可是這裏,咱們仍是想要列出一些其它可選的測試方法。

phpspec

除了 PHPUnit 以外,Laravel 5.1還提供了開箱即用的 phpspec。這是另外一個流行的 PHP 單元測試工具,聚焦於行爲驅動開發(BDD)。

下面是 phpspec 的一些說明:

  • 安裝在 vendor/bin 目錄下,所以能夠在項目根目錄中直接運行 phpspec
  • 配置文件是位於項目根目錄下的 phpspec.yml
  • 要從 Gulp 中運行 phpspec,能夠調用 mix 對象上的 phpSpec() 函數
  • 若是你將應用的命名空間名稱 App 改爲了其它的,須要修改 phpspec.yml 中相應的配置

單元測試

儘管說到 PHP 單元測試,PHPUnit 已經成爲事實上的標準方式,但仍是有一些其餘單元測試包可供使用:

功能測試

這種測試是對整個應用進行測試而不是僅僅驗證應用中的某個片斷。當使用 Laravel 5.1 提供的測試方法時,還可使用  PHPUnit 進行一些功能測試。ExampleTest.php 中提供了一個簡單的示例,可是還有專門的測試框架專一於功能測試:

行爲驅動開發(BDD)

BDD 有兩個分支:SpecBDD 和 StoryBDD

SpecBDD 專一於代碼的技術層面,Laravel 5.1 自帶的 phpspec 是標準的SpecDD

StoryBDD 則強調商業或者功能測試,Behat 是最流行的 StoryBDD 框架,此外,Codeception 也能夠用做 StoryBDD。

相關文章
相關標籤/搜索