<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                ??碼云GVP開源項目 12k star Uniapp+ElementUI 功能強大 支持多語言、二開方便! 廣告
                _有的時候寧愿付錢讓你一周在床上待著,也不想讓你用這周剩下的時間去調試你在周一所寫的代碼。 --丹·所羅門_ ##2.14.1 測試驅動開發 做正確的事,比把事情做正確更為重要。 當明確需要做何事后,再通過事先編寫單元測試來準確表達我們將要實現的功能,是相當具有指導意義的。你會發現接下來你的開發歷程就是:單元測試-設計-重構,而且這種正向循環是很有創造性的,并且進行到一定程度后會慢慢體會到浮現式設計的樂趣。 關于測試驅動開發TDD,有很多資料已進行了說明,這里不再贅述。 如果還沒了解PHPUnit,可先閱讀:[PHPUnit 手冊](https://phpunit.de/manual/3.7/zh_cn/automating-tests.html) 如果還沒了解PHPUnit,可先閱讀:[PHPUnit 手冊](https://phpunit.de/manual/3.7/zh_cn/automating-tests.html) 如果還沒了解PHPUnit,可先閱讀:[PHPUnit 手冊](https://phpunit.de/manual/3.7/zh_cn/automating-tests.html) ##2.14.2 意圖導向編程 ![apic](http://webtools.qiniudn.com/20150411005257_2bc8683a50ac1d620cef4e39918ed3e5) 在編寫代碼前,先寫測試代碼,更容易提高 **關注點** 。 因為,在開發過程中, 大多時候會被外界打斷(如需求溝通、線上問題處理、臨時會議等),而通過單元測試則可以讓你“幾乎忘卻需要做什么”的情況下重新讓你回到之前的狀態,特別在并行開發多個不同項目的需求時尤其重要。 除此之外,遵循“紅-綠-重構”這樣的流程,我們可以在更高的層面關注需要實現的功能需求,并自頂而下地進行設計優化,精益代碼。 ##2.14.3 編寫測試的原則、模式和指導 首先應該意識到,測試代碼和生產代碼一樣重要。其次,測試代碼也應該和生產代碼一樣被同步維護更新,這樣才能保持生氣,更大地發揮作用。只有當不斷地對測試的代碼進行修修補被,我們才能保持自動化測試這張“安全網”常新。 ##2.14.4 F.I.R.S.T.原則 + 快速 Fast + 獨立 Independent + 可重復 Repeatable + 自足驗證 Self-validating + 及時 Timely ##2.14.5 構造-操作-檢驗(BUILD-OPERATE-CHECK)模式 這個模式也可以理解成:“當... 做...應該...”。其中,構造包括測試環境的搭建、測試數據前期的準備;操作是指對被測試對象的調用, 以及被測試對象之間的通信和協助交互;最后檢驗則是對業務規則的斷言、對功能需求的驗證。 ##2.14.6 如何編寫高效測試代碼 + 1、與產品代碼分開,與測試代碼對齊 + 2、利用測試骨架(phpunit-skelgen或者自定義生成器)自動生成測試代碼 + 3、使用測試替身、測試樁構建昂貴資源、制造異常情況 + 4、每個測試一個概念 ##2.14.7 PhalApi開發下的單元測試 我們推薦在各自的項目代碼中平行編寫單元測試,并逐漸完善、保持同步。以下是進行單元測試的參考。 ###(1)Api接口層的單元測試 Api接口層,是我們后臺開發的主要切入點,也是直接對外提供服務的入口,屬于更高層次的概念并擁有指定的業務功能,更是后臺開發的關注點。所以在對新接口進行開發前,編寫單元測試是非常有意義的。 為了可以自動生成測試代碼,我們可以先簡單定義好接口的函數簽名(以獲取用戶基本信息接口為例): ```javascript //$ vim ./Demo/Api/User.php <?php class Api_User extends PhalApi_Api { public function getBaseInfo() { } } ``` 隨后,自動生成測試代碼骨架: ```javascript $ mkdir ./Demo/Tests/Api -p $ cd ./Demo/Tests/Api $ php ./PhalApi/build_phpunit_test_tpl.php ./Demo/Api/User.php Api_User ./Public/init.php $ php ./PhalApi/build_phpunit_test_tpl.php ./Demo/Api/User.php Api_User ./Public/init.php > ./Demo/Tests/Api/Api_User_Test.php ``` 根據接口的需要,驗證接口返回的格式,以及業務數據的正確性。 ```javascript //$ vim ./Demo/Tests/Api/Api_User_Test.php /** * @group testGetBaseInfo */ public function testGetBaseInfo() { //Step 1. 構建請求URL $str = 'service=User.GetBaseInfo&user_id=1'; //Step 2. 執行請求 $rs = PhalApi_Helper_TestRunner::go($url); //Step 3. 驗證 $this->assertNotEmpty($rs); $this->assertArrayHasKey('code', $rs); $this->assertArrayHasKey('msg', $rs); $this->assertArrayHasKey('info', $rs); $this->assertEquals(0, $rs['code']); $this->assertEquals('dogstar', $rs['info']['name']); $this->assertEquals('oschina', $rs['info']['note']); } ``` 上面的驗證意思簡單明了,結合 **構造-操作-檢驗(BUILD-OPERATE-CHECK)模式** 加以說明一下。 ###構造:構建請求URL ```javascript //Step 1. 構建請求URL $str = 'service=User.GetBaseInfo&user_id=1'; ``` 此參數即對應接口請求的URL參數,我們將此參數追加在接口入口并在瀏覽器打開可以得到同樣的接口執行效果。但這樣的好處更在于通過單元測試幫我們記住了各種接口測試的業務場景。而不再是像以前那樣打開N個瀏覽器窗口人工進行調試,也不用像以前那樣苦苦尋找瀏覽器記錄。 如果接口需要POST數據,或者其他更多參數,可以使用$params來傳遞更多參數,一如: ``` //Step 1. 構建請求URL $str = 'service=User.GetBaseInfo&user_id=1'; $params = array(); //更多參數 //Step 2. 執行請求 $rs = PhalApi_Helper_TestRunner::go($url, $params); //通過第二個參數,傳送更多參數 ``` ####操作:執行請求 這里的操作,顯然就是對應我們接口的調用。簡單地如: ```javascript //Step 2. 執行請求 $rs = PhalApi_Helper_TestRunner::go($url); ``` 這樣,便可以在服務端模擬進行一次接口的請求調度,注意這里是在服務端進行的接口請求,而不是客戶端。 此外,如果需要傳遞更多參數,可以參考前面的示例。這里簡單補充一下PhalApi_Helper_TestRunner測試輔助類的接口簽名說明: ``` <?php class PhalApi_Helper_TestRunner { /** * @param string $url 請求的鏈接 * @param array $param 額外POST的數據 * @return array 接口的返回結果 */ public static function go($url, $params = array()) { ... ... ``` ####檢驗:驗證 在對接口返回的結果中,我們可以這樣依次進行正確性的驗證: + 1、先驗證接口返回的格式是否正確,有無字段遺漏; + 2、返回的業務數據是否正確; ```javascript //Step 3. 驗證 $this->assertNotEmpty($rs); $this->assertArrayHasKey('code', $rs); $this->assertArrayHasKey('msg', $rs); $this->assertArrayHasKey('info', $rs); $this->assertEquals(0, $rs['code']); $this->assertEquals('dogstar', $rs['info']['name']); $this->assertEquals('oschina', $rs['info']['note']); ``` 由于測試環境的數據變動頻繁,所以我們可以針對個別的接口進行更精確的驗證,而對類似列表獲取這樣的大批量的數據,則校驗其結構格式。 除此之外,還有一種情況也是需要納入檢驗,即除了上面的正常請求情況下的 **異常請求** 。 接下來的即是之前文檔里面所說的單元測試執行和接口開發,此處略。 ###(2)Domain層和Model層的單元測試 下面繼續簡單補充一下之前沒談及到的Domain層和Model層的單元測試。 顯然,這兩層的開發,已經在前面的接口測試驅動開發的指導下很好地完成了。現在可以快速追加對這兩層的單元測試。得益于我們的生成測試骨架的腳本,操作如下: ```javascript $ php ./PhalApi/build_phpunit_test_tpl.php ./Demo/Domain/User.php Domain_User > ./Demo/Tests/Domain/Domain_User_Test.php $ php ./PhalApi/build_phpunit_test_tpl.php ./Demo/Model/User.php Model_User > ./Demo/Tests/Model/Model_User_Test.php ``` 接著,修改一下測試環境 **test_env.php**的引用路徑: ```javascript //$ vim ./Demo/Tests/Domain/Domain_User_Test.php //$ vim ./Demo/Tests/Model/Model_User_Test.php require_once dirname(__FILE__) . '/../test_env.php'; ``` 各自完善一下單元測試: ```javascript //$ vim ./Demo/Tests/Domain/Domain_User_Test.php /** * @group testGetBaseInfo */ public function testGetBaseInfo() { $userId = '1'; $rs = $this->domainUser->getBaseInfo($userId); $this->assertArrayHasKey('id', $rs); $this->assertArrayHasKey('name', $rs); $this->assertArrayHasKey('note', $rs); $this->assertEquals('dogstar', $rs['name']); } ``` 執行一下: ```javascript $ phpunit ./Demo/Tests/Domain/Domain_User_Test.php PHPUnit 4.3.4 by Sebastian Bergmann. . Time: 49 ms, Memory: 6.25Mb OK (1 test, 4 assertions) ``` ###(3)Model層的單元測試 Model層的單元測試類似,不再贅述。 ##2.14.7 更進一步的單元測試套件 到目前為止,我們有了如下的產品代碼: ```javascript dogstar@ubuntu:Demo$ tree . ├── Api │?? └── User.php ├── Domain │?? └── User.php ├── Model │?? └── User.php ``` 并擁有了與之平行對應的單元測試: ```javascript dogstar@ubuntu:Tests$ tree . ├── Api │?? └── Api_User_Test.php ├── Domain │?? └── Domain_User_Test.php ├── Model │?? └── Model_User_Test.php └── test_env.php ``` 這樣是一個很好的開始,但若我們每次測試都分別調用三次這些不同層次的單元測試,顯然有點不科學。所以,利用PHPUnit的配置文件,我們可以輕松管理我們的測試套件,如: ```javascript dogstar@ubuntu:Tests$ vim ./phpunit_user_getbaseinfo.xml <?xml version="1.0" encoding="UTF-8"?> <phpunit backupGlobals="false" ... <testsuites> <testsuite name="Test Suite"> <file>./Api/Api_User_Test.php</file> <file>./Domain/Domain_User_Test.php</file> <file>./Model/Model_User_Test.php</file> </testsuite> </testsuites> </phpunit> ``` 啊哈!終于,當需要調用這些分布在不同目錄位置的單元測試時,只需要這么簡單的一行命令: ```javascript dogstar@ubuntu:Tests$ phpunit -c ./phpunit_user_getbaseinfo.xml PHPUnit 4.3.4 by Sebastian Bergmann. ..... Time: 54 ms, Memory: 7.25Mb OK (5 tests, 28 assertions) ``` ##2.14.8 這樣的好處? 上面的過程,細節較多,而且需要實際操作的部分也比較多。對于之前沒有接觸過單元測試這塊的同學,可能會有點迷茫,對于不愿意接受單元測試的同學來說更加枯燥。 然而,然而。 當我們把越痛苦的事情越早完成后,我們后面就順暢多了。正如在某一次培訓中的某一位敏捷開發的專家所說的: _要逐步對小問題做優化,而不是要等到大問題到來時再做變革_ 。 ###那這樣的好處在于哪里呢? 這里不就理論回答,而是以我個人的經歷來簡單說明。 首先,正如上面所說的,單元測試幫你很好地記住并整理了各種接口測試的場景,而不用再像以前那樣打開N個瀏覽器窗口逐個人工校對。 其次,在單元測試的論證下我們可以更有信心地跟測試說、跟產品說、跟發布說我們的代碼沒問題,因為我們通過嚴格的單元測試,而不是人為主觀上的想當然應該不會有問題吧。 最后,也是最重要的,在后期的接口升級、改動和維護中,單元測試再一次為我們提供了保護,猶如一張安全網,涵蓋我們改動的每一處代碼。與此同時,對于重構也亦然。 但單元測試所帶給你的,不僅僅是上面所說的簡單這幾點。更多地完全不一樣的開發歷程,而其中滋味和令人興奮的體現,只有當你親自去嘗試才會明白其中滋味。So, try it by yourself.
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看