乡下人产国偷v产偷v自拍,国产午夜片在线观看,婷婷成人亚洲综合国产麻豆,久久综合给合久久狠狠狠9

  • <output id="e9wm2"></output>
    <s id="e9wm2"><nobr id="e9wm2"><ins id="e9wm2"></ins></nobr></s>

    • 分享

      PHPUnit 手冊(cè)【筆記】

       硬核項(xiàng)目經(jīng)理 2021-05-31

      一、安裝
      composer require --dev phpunit/phpunit ^6.5
      composer require --dev phpunit/dbunit

      二、編寫測(cè)試
      A.PHPUnit編寫測(cè)試

      1.基本慣例與步驟:

      * 針對(duì)類Class的測(cè)試寫在類ClassTest中
      * ClassTest(通常)繼承自PHPUnit\Framework\TestCase
      * 測(cè)試都是命名為test*的公用方法,也可以在方法的文檔注釋塊(docblock)中使用@test標(biāo)注將其標(biāo)記為測(cè)試方法
      * 在測(cè)試方法內(nèi),類似于assertEquals()這樣的斷言方法用來對(duì)實(shí)際值與預(yù)期值的匹配做出斷言

      2.當(dāng)你想把一些東西寫到print語(yǔ)句或者調(diào)試表達(dá)式中時(shí),別這么做,將其寫成一個(gè)測(cè)試來代替

      StackTest.php

      B.測(cè)試的依賴關(guān)系
      1.單元測(cè)試主要是作為一種良好實(shí)踐來編寫的,它能幫助開發(fā)人員識(shí)別并修復(fù) bug、重構(gòu)代碼,還可以看作被測(cè)軟件單元的文檔。要實(shí)現(xiàn)這些好處,理想的單元測(cè)試應(yīng)當(dāng)覆蓋程序中所有可能的路徑。一個(gè)單元測(cè)試通常覆蓋一個(gè)函數(shù)或方法中的一個(gè)特定路徑。但是,測(cè)試方法并不一定非要是一個(gè)封裝良好的獨(dú)立實(shí)體。測(cè)試方法之間經(jīng)常有隱含的依賴關(guān)系暗藏在測(cè)試的實(shí)現(xiàn)方案中
      2.PHPUnit支持對(duì)測(cè)試方法之間的顯式依賴關(guān)系進(jìn)行聲明。這種依賴關(guān)系并不是定義在測(cè)試方法的執(zhí)行順序中,而是允許生產(chǎn)者(producer)返回一個(gè)測(cè)試基境(fixture)的實(shí)例,并將此實(shí)例傳遞給依賴于它的消費(fèi)者(consumer)們

      * 生產(chǎn)者,是能生成被測(cè)單元將其作為返回值的測(cè)試方法
      * 消費(fèi)者,是依賴于一個(gè)或多個(gè)生產(chǎn)者及其返回值的測(cè)試方法

      3.使用@depends標(biāo)注來表達(dá)測(cè)試方法之間的依賴關(guān)系,如果需要傳遞對(duì)象副本而非引用,則應(yīng)當(dāng)用@depends clone替代@depends
      4.測(cè)試可以使用多個(gè)@depends標(biāo)注,需要保證某個(gè)測(cè)試所依賴的所有測(cè)試均出現(xiàn)于這個(gè)測(cè)試之前
      5.擁有多個(gè)@depends標(biāo)注的測(cè)試,其第一個(gè)參數(shù)是每一個(gè)生產(chǎn)者提供的基境,第二個(gè)參數(shù)是第二個(gè)生產(chǎn)者提供的基境,以此類推

      MultipleDependenciesTest.php、DependencyFailureTest.php、DependencyAndDataProviderComboTest.php

      C.數(shù)據(jù)供給器
      1.測(cè)試方法可以接受任意參數(shù)。這些參數(shù)由數(shù)據(jù)供給器方法提供。用@dataProvider標(biāo)注來指定使用哪個(gè)數(shù)據(jù)供給器方法
      2.數(shù)據(jù)供給器方法必須聲明為public,其返回值要么是一個(gè)數(shù)組,其每個(gè)元素也是數(shù)組;要么是一個(gè)實(shí)現(xiàn)了Iterator接口的對(duì)象。每個(gè)數(shù)組都是測(cè)試數(shù)據(jù)集的一部分,將以它的內(nèi)容作為參數(shù)來調(diào)用測(cè)試方法
      3.當(dāng)使用到大量數(shù)據(jù)集時(shí),最好逐個(gè)用字符串鍵名對(duì)其命名,避免用默認(rèn)的數(shù)字鍵名,這樣輸出的信息會(huì)更加詳細(xì)些
      4.如果測(cè)試同時(shí)從@dataProvider方法和一個(gè)或多個(gè)@depends測(cè)試接收數(shù)據(jù),那么來自于數(shù)據(jù)供給器的參數(shù)將先于來自所依賴的測(cè)試參數(shù)
      5.如果一個(gè)測(cè)試依賴于另一個(gè)使用了數(shù)據(jù)供給器的測(cè)試,僅當(dāng)被依賴的測(cè)試至少能在一組數(shù)據(jù)上成功時(shí),依賴于它的測(cè)試才會(huì)運(yùn)行。使用了數(shù)據(jù)供給器的測(cè)試,其運(yùn)行結(jié)果是無法注入到依賴于此測(cè)試的其他測(cè)試中的
      6.所有的數(shù)據(jù)供給器方法的執(zhí)行都是在對(duì)setUpBeforeClass靜態(tài)方法的調(diào)用和第一次對(duì)setUp方法的調(diào)用之前完成的。因此,無法在數(shù)據(jù)供給器中使用創(chuàng)建于這兩個(gè)方法內(nèi)的變量。這樣PHPUnit才能計(jì)算測(cè)試的總數(shù)量。

      DataTest.php

      D.對(duì)異常進(jìn)行測(cè)試
      1.使用expectException()、expectExceptionCode()、expectExceptionMessage()、expectExceptionMessageRegExp()方法可以為被測(cè)代碼所拋出的異常建立預(yù)期
      2.也可以用@expectException、@expectExceptionCode、@expectExceptionMessage、@expectExceptionMessageRegExp標(biāo)注

      ExceptionTest.php、ExpectedErrorTest.php

      E.對(duì)PHP錯(cuò)誤進(jìn)行測(cè)試
      1.默認(rèn)情況下PHPUnit將測(cè)試在執(zhí)行中觸發(fā)的PHP錯(cuò)誤、警告、通知都轉(zhuǎn)換為異常
      2.PHP的error_reporting運(yùn)行時(shí)配置會(huì)對(duì)PHPUnit將哪些錯(cuò)誤轉(zhuǎn)換為異常有所限制
      3.對(duì)異常進(jìn)行測(cè)試是越明確越好,對(duì)太籠統(tǒng)的類進(jìn)行測(cè)試有可能導(dǎo)致不良副作用
      4.如果測(cè)試依靠會(huì)觸發(fā)錯(cuò)誤的PHP函數(shù),例如fopen,有時(shí)候在測(cè)試中使用錯(cuò)誤抑制符會(huì)很有用。通過抑制住錯(cuò)誤通知,就能對(duì)返回值進(jìn)行檢查,否則會(huì)導(dǎo)致拋出異常

      ErrorSuppressionTest.php

      F.對(duì)輸出進(jìn)行測(cè)試
      1.有時(shí)候,想要斷言(比如說)某方法的運(yùn)行過程中生成了預(yù)期的輸出(通過echo或print)。PHPUnit\Framework\TestCase類使用PHP的輸出緩沖特性來為此提供必要的功能支持
      2.使用expectOutputString()方法來設(shè)定所預(yù)期的輸出,如果沒有產(chǎn)生預(yù)期的輸出,測(cè)試將計(jì)為失敗
      3.輸出進(jìn)行測(cè)試的方法

      * expectOutputRegex(string $regularExpression)設(shè)置輸出預(yù)期為輸出應(yīng)當(dāng)匹配正則表達(dá)式
      * expectOutputString(string @expectedString)設(shè)置輸出預(yù)期為輸出應(yīng)當(dāng)與$expectedString字符串相等
      * setOutputCallback(callable $callback)設(shè)置回調(diào)函數(shù),用來做諸如將實(shí)際輸出規(guī)范化之類的動(dòng)作
      * string getActualOutpu()獲取實(shí)際輸出

      4.嚴(yán)格模式下本身產(chǎn)生輸出的測(cè)試將會(huì)失敗

      OutputTest.php

      G.錯(cuò)誤相關(guān)信息的輸出
      1.當(dāng)有測(cè)試失敗時(shí),PHPUnit全力提供盡可能多的有助于找出問題所在的上下文信息
      2.當(dāng)生成的輸出很長(zhǎng)而難以閱讀時(shí),PHPUnit將對(duì)其進(jìn)行分割,并在每個(gè)差異附近提供少數(shù)幾行上下文信息

      三、命令行測(cè)試執(zhí)行器
      1.對(duì)于每個(gè)測(cè)試的運(yùn)行,PHPUint命令行工具輸出一個(gè)字符來指示進(jìn)展:

      【.】當(dāng)測(cè)試成功時(shí)輸出
      【F】當(dāng)測(cè)試方法運(yùn)行過程中一個(gè)斷言失敗時(shí)輸出
      【E】當(dāng)測(cè)試方法運(yùn)行過程中產(chǎn)生一個(gè)錯(cuò)誤時(shí)輸出
      【R】當(dāng)測(cè)試被標(biāo)記為有風(fēng)險(xiǎn)時(shí)輸出
      【S】當(dāng)測(cè)試被跳過時(shí)輸出
      【I】當(dāng)測(cè)試被標(biāo)記為不完整或未實(shí)現(xiàn)時(shí)輸出

      2.PHPUnit區(qū)分失敗(failure)與錯(cuò)誤(error),失敗是違背了PHPUnit斷言,錯(cuò)誤是意料之外的異常,錯(cuò)誤往往比失敗更容易修復(fù)

      A.命令行選項(xiàng)

      * -h|--help,幫助
      * UnitTest,運(yùn)行由UnitTest類提供的測(cè)試
      * --coverage-clover,為運(yùn)行的測(cè)試生成帶有代碼覆蓋率信息的XML格式的日志文件,僅當(dāng)安裝了tokenizer和Xdebug這兩個(gè)PHP擴(kuò)展后才可用
      * --coverage-crap4j,生成Crap4j格式的代碼覆蓋率報(bào)告,僅當(dāng)安裝了tokenizer和Xdebug這兩個(gè)PHP擴(kuò)展后才可用
      * --coverage-html,生成HTML格式的代碼覆蓋率報(bào)告,僅當(dāng)安裝了tokenizer和Xdebug這兩個(gè)PHP擴(kuò)展后才可用
      * --coverage-php,生成一個(gè)序列化后的PHP_CodeCoverage對(duì)象,此對(duì)象含有代碼覆蓋率信息,僅當(dāng)安裝了tokenizer和Xdebug這兩個(gè)PHP擴(kuò)展后才可用
      * --coverage-text,為運(yùn)行的測(cè)試以人們可讀的格式生成帶有代碼覆蓋率信息的日志文件或命令行輸出,僅當(dāng)安裝了tokenizer和Xdebug這兩個(gè)PHP擴(kuò)展后才可用
      * --log-junit,為運(yùn)行的測(cè)試生成JUnit XML格式的日志文件
      * --testdox-html和--testdox-text,為運(yùn)行的測(cè)試以HTML或純文本格式生成敏捷文檔
      * --filter,只運(yùn)行與給定模式匹配的測(cè)試
      * --testsuite,只運(yùn)行名稱與給定模式匹配的測(cè)試套件
      * --group,只運(yùn)行來自指定分組(可以多個(gè))的測(cè)試??梢杂聾group標(biāo)注為測(cè)試標(biāo)記其所屬的分組,@author標(biāo)注是@group的一個(gè)別名,允許按作者來篩選測(cè)試
      * --exclude-group,排除來自指定分組的測(cè)試
      * --list-groups,列出所有有效的測(cè)試分組
      * --test-suffix,只查找文件名以指定后綴(可以多個(gè))結(jié)尾的測(cè)試文件
      * --report-useless-tests,更嚴(yán)格對(duì)待事實(shí)上不測(cè)試任何內(nèi)容的測(cè)試
      * --strict-global-state,更嚴(yán)格對(duì)待全局狀態(tài)篡改
      * --strict-coverage,更嚴(yán)格對(duì)待意外的代碼覆蓋
      * --disallow-test-output,更嚴(yán)格對(duì)待測(cè)試執(zhí)行期間產(chǎn)生的輸出
      * --disallow-todo-tests,不執(zhí)行文檔注釋塊中含有@todo標(biāo)注的測(cè)試
      * --enforce-time-limit,根據(jù)測(cè)試規(guī)模對(duì)其加上執(zhí)行時(shí)長(zhǎng)限制
      * --process-isolation,每個(gè)測(cè)試都在獨(dú)立的PHP進(jìn)程中運(yùn)行
      * --no-globals-backup,不要備份并還原$GLOBALS
      * --static-backup,備份并還原用戶定義的類中的靜態(tài)屬性
      * --colors,使用彩色輸出,三個(gè)值:never完全不使用,auto當(dāng)前終端默認(rèn),always總是彩色輸出
      * --columns,定義輸出所使用的列數(shù)
      * --stderr,選擇輸出到STDERR而非STDOUT
      * --stop-on-error,首次錯(cuò)誤出現(xiàn)后停止執(zhí)行
      * --stop-on-failure,首次錯(cuò)誤或失敗后停止執(zhí)行
      * --stop-on-risky,首次踫到有風(fēng)險(xiǎn)的測(cè)試時(shí)停止執(zhí)行
      * --stop-on-skipped,首次碰到到跳過的測(cè)試時(shí)停止執(zhí)行
      * --stop-on-incomplete,首次碰到不完整的測(cè)試時(shí)停止執(zhí)行
      * --verbose,輸出更詳盡的信息,如不完整或跳過的測(cè)試的名稱
      * --debug,輸出調(diào)試信息,如當(dāng)一個(gè)測(cè)試開始執(zhí)行時(shí)輸出其名稱
      * --loader,指定要使用的PHPUnit_Runner_TestSuiteLoader實(shí)現(xiàn)
      * --repeat,將測(cè)試重復(fù)運(yùn)行指定次數(shù)
      * --testdox,將測(cè)試進(jìn)度以敏捷文檔方式報(bào)告
      * --printer,指定要使用的結(jié)果輸出器(printer)
      * --bootstrap,在測(cè)試前先運(yùn)行一個(gè)“bootstrap”PHP文件
      * --configuration,-c,從XML文件中讀取配置信息
      * --no-configuration,忽略當(dāng)前工作目錄下的phpunit.xml與phpunit.xml.dist
      * --include-path,向PHP的include_path開頭添加指定路徑(可以多個(gè))
      * -d,設(shè)置指定的PHP配置選項(xiàng)的值


      四、基境(fixture)
      1.在編寫測(cè)試時(shí),最費(fèi)時(shí)的部分之一是編寫代碼來將整個(gè)場(chǎng)景設(shè)置成某個(gè)已知的狀態(tài),并在測(cè)試結(jié)束后將其復(fù)原到初始狀態(tài),這個(gè)已知的狀態(tài)稱為測(cè)試的基境(fixture)
      2.PHPUnit支持共享建立基境的代碼,在運(yùn)行某個(gè)測(cè)試方法前,會(huì)調(diào)用一個(gè)名叫setUp()的模板方法,setUp()是創(chuàng)建測(cè)試所用對(duì)象的方法,當(dāng)測(cè)試方法運(yùn)行結(jié)束后,不管成功還是失敗,都會(huì)調(diào)用另外一個(gè)名叫tearDown()的模板方法,清理測(cè)試所有對(duì)象的方法
      3.測(cè)試類的每個(gè)測(cè)試方法都會(huì)運(yùn)行一次setUp()和tearDown()模板方法,setUpBeforeClass()和tearDownAfterClass()模板方法將分別在測(cè)試用例類的第一個(gè)測(cè)試運(yùn)行之前和測(cè)試用例類的最后一個(gè)測(cè)試運(yùn)行之后調(diào)用
      4.在setUp()中分配了諸如文件或套接字之類的外部資源時(shí)才需要實(shí)現(xiàn)tearDown(),如果setUp()中只創(chuàng)建純PHP對(duì)象,通??梢院雎詔earDown()
      5.如果兩個(gè)setUp()代碼有微小差異,把有差異的內(nèi)容從setUp()移到測(cè)試方法內(nèi);如果兩個(gè)setUp()是確實(shí)不一樣,那么需要另外一個(gè)測(cè)試用例類
      6.在測(cè)試之間共享基境的需求都源于某個(gè)未解決的設(shè)計(jì)問題,有實(shí)際意義的多測(cè)試間共享基境的例子是數(shù)據(jù)庫(kù)鏈接
      7.在測(cè)試之間共享基境會(huì)降低測(cè)試的價(jià)值,潛在的設(shè)計(jì)問題是對(duì)象之間并非松散耦合
      8.使用單件(singleton)的代碼很難測(cè)試,使用全局變量的代碼也一樣,代碼與全局變量之間會(huì)強(qiáng)烈耦合,一個(gè)測(cè)試對(duì)全局變量的改變可能會(huì)影響另一個(gè)
      9.$backupGlobalsBlacklist,變量可以提供全局變量黑名單;@backupGlobals標(biāo)注可以用來控制對(duì)全局變量的備份與還原操作;@backupStaticAttributes標(biāo)注可以用于在每個(gè)測(cè)試之前備份所有已聲明類的靜態(tài)屬性值并在其后恢復(fù)

      StackTest4.php、TemplateMethodsTest.php、Database4_3.php

      五、組織測(cè)試
      A.用文件系統(tǒng)來編排測(cè)試套件
      1.把所有測(cè)試用例源文件放在一個(gè)測(cè)試目錄中,通過對(duì)測(cè)試目錄進(jìn)行遞歸遍歷,PHPUnit能自動(dòng)發(fā)現(xiàn)并運(yùn)行測(cè)試
      2.這種方法的缺點(diǎn)是無法控制測(cè)試的運(yùn)行順序,可能導(dǎo)致測(cè)試的依賴關(guān)系方面的問題

      B.用XML配置來編排測(cè)試套件
      1.如果phpunit.xml或phpunit.xml.dist存在于當(dāng)前工作目錄并且未使用--configuration,將自動(dòng)從此文件中讀取配置

      /5_1test/phpunit.xml

      六、有風(fēng)險(xiǎn)的測(cè)試
      1.PHPUnit可以更嚴(yán)格對(duì)待事實(shí)上不測(cè)試任何內(nèi)容的測(cè)試,可以用命令行--report-useless-tests或在PHPUnit的XML中設(shè)置beStrictAboutTestsThatDoNotTestAnything="true"來啟用,如果某個(gè)測(cè)試未時(shí)行任何斷言,它將被標(biāo)記為有風(fēng)險(xiǎn)
      2.可以更嚴(yán)格對(duì)待意外的代碼覆蓋,用命令行--strict-coverage或在XML配置文件中設(shè)置beStrictAboutCoversAnnotation="true"來啟用,如果某個(gè)帶有@covers標(biāo)注的測(cè)試執(zhí)行了未在@covers或@uses標(biāo)注中列出的代碼,它將被標(biāo)記為有風(fēng)險(xiǎn)
      3.可以更嚴(yán)格對(duì)待測(cè)試執(zhí)行期間產(chǎn)生的輸出,用命令行--disallow-test-output或在XML中設(shè)置beStrictAboutOutputDuringTests ="true"來啟用,如果某個(gè)測(cè)試產(chǎn)生了輸出,將被標(biāo)記為有風(fēng)險(xiǎn)
      4.測(cè)試執(zhí)行時(shí)長(zhǎng)的超時(shí)限制,如果安裝了PHP_Invoker包并且pcntl擴(kuò)展可用,可以對(duì)測(cè)試的執(zhí)行時(shí)長(zhǎng)進(jìn)行限制
      5.可以更嚴(yán)格的對(duì)待篡改全局狀態(tài)的測(cè)試,用命令行--strict-global-state或在XML中配置beStrictAboutChangesToGlobalState="true"

      七、未完成的測(cè)試與跳過的測(cè)試
      A.未完成的測(cè)試
      1.空測(cè)試的問題是PHPUnit框架會(huì)將它們解讀為成功
      2.PHPUnit_Framework_IncompleteTest是一個(gè)標(biāo)記接口,用于將測(cè)試方法拋出的異常標(biāo)記為測(cè)試未完成或目前尚未實(shí)現(xiàn)而導(dǎo)致的結(jié)果,PHPUnit_Framework_IncompleteTestError是這個(gè)接口的標(biāo)準(zhǔn)實(shí)現(xiàn)
      4.命令行測(cè)試執(zhí)行器中的輸出標(biāo)記為I
      5.用于未完成測(cè)試的API,void markTestIncomplete(string $message),將當(dāng)前測(cè)試標(biāo)記為未完成,并用$message作為說明信息

      B.跳過測(cè)試
      1.并非所有測(cè)試都能在任何環(huán)境中運(yùn)行,用markTestSkipped()方法來跳過此測(cè)試
      2.命令行測(cè)試執(zhí)行器中的輸出標(biāo)記為S(測(cè)試是R)
      3.用于跳過測(cè)試的API,void markTestSkipped(string $message),將當(dāng)前測(cè)試標(biāo)記為已跳過,并用$message作為說明信息

      C.用@requires來跳過測(cè)試
      1.可以用@requires標(biāo)注來跳過測(cè)試用例的一些常見前提條件

      * @requires PHP 5.3|7.1……,PHP版本
      * @requires PHPUnit 3.6.3…… PHPUnit版本
      * @requires OS Linux|WIN32|WINNT 系統(tǒng)版本
      * @requires function 任何對(duì)于 function_exists而言有效的參數(shù)
      * @requires extension 任何擴(kuò)展模塊名


      SampleTest7_1.php、DatabaseTest7_2.php、DatabaseTest7_3.php

      八、數(shù)據(jù)庫(kù)測(cè)試
      A.數(shù)據(jù)庫(kù)測(cè)試的難點(diǎn)
      1.需要考慮的變數(shù):

      * 數(shù)據(jù)庫(kù)和表
      * 向表中插入測(cè)試所需要的行
      * 測(cè)試運(yùn)行完畢后驗(yàn)證數(shù)據(jù)庫(kù)的狀態(tài)
      * 每個(gè)新測(cè)試都要清理數(shù)據(jù)庫(kù)

      2.測(cè)試代碼應(yīng)當(dāng)盡可能簡(jiǎn)短精簡(jiǎn):

      * 你不希望因?yàn)樯a(chǎn)代碼的小變更而需要對(duì)測(cè)試代碼進(jìn)行數(shù)據(jù)可觀的修改
      * 你希望在哪怕好幾個(gè)月以后也能輕松地閱讀并理解測(cè)試代碼

      3.本質(zhì)上說,數(shù)據(jù)庫(kù)是全局輸入變量

      B.數(shù)據(jù)庫(kù)測(cè)試的四個(gè)階段
      1.單元測(cè)試四個(gè)階段:

      * 建立基境(fixture)
      * 執(zhí)行被測(cè)系統(tǒng)
      * 驗(yàn)證結(jié)果
      * 拆除基境(fixture)

      2.數(shù)據(jù)庫(kù)擴(kuò)展進(jìn)行測(cè)試的流程:

      * 清理數(shù)據(jù)庫(kù):在所有表上執(zhí)行TRUNCATE操作清空
      * 建立基境:將迭代所有指定的基境數(shù)據(jù)行并將其插入到對(duì)應(yīng)的表里
      * 運(yùn)行測(cè)試
      * 驗(yàn)證結(jié)果
      * 拆除基境


      C.PHPUnit數(shù)據(jù)庫(kù)測(cè)試用例的配置
      1.如果測(cè)試代碼用到了數(shù)據(jù)庫(kù)擴(kuò)展模塊,需要擴(kuò)展另一個(gè)抽象TestCase(PHPUnit\DbUnit\TestCaseTrait)類,要求實(shí)現(xiàn)getConnection()和getDataSet()
      2.PHPUnit的數(shù)據(jù)庫(kù)擴(kuò)展模塊需要用PDO庫(kù)來實(shí)現(xiàn)跨供應(yīng)商抽象訪問數(shù)據(jù)庫(kù)連接,PDO連接僅僅用于清理和建立基境
      3.getDataSet()方法定義了在每個(gè)測(cè)試執(zhí)行之前的數(shù)據(jù)庫(kù)初始狀態(tài)應(yīng)該是什么樣,數(shù)據(jù)庫(kù)的狀態(tài)由PHPUnit_Extensions_Database_DataSet_IDataSet所代表的DataSet數(shù)據(jù)集和由PHPUnit_Extensions_Database_DataSet_IDataTable所代表的DataTable數(shù)據(jù)表這兩個(gè)概念進(jìn)行抽象
      4.setUp()中會(huì)調(diào)用一次getDataSet()方法來接收基境數(shù)據(jù)集并將其插入數(shù)據(jù)庫(kù)

      D.理解DataSet(數(shù)據(jù)集)和DataTable(數(shù)據(jù)表)
      1.DataSet和DataTable是圍繞著數(shù)據(jù)庫(kù)表、行、列的抽象層,通過一套簡(jiǎn)單的API,底層數(shù)據(jù)庫(kù)內(nèi)容被隱藏在對(duì)象結(jié)構(gòu)之下,這個(gè)對(duì)象結(jié)構(gòu)也可以用其他非數(shù)據(jù)庫(kù)數(shù)據(jù)源來實(shí)現(xiàn)
      2.預(yù)期內(nèi)容可以用諸如XML、YAML、CSV文件或者PHP數(shù)組等方式來表達(dá)
      3.在測(cè)試中,數(shù)據(jù)庫(kù)斷言的工作流由三個(gè)步驟組成:

      * 用表名稱來指定數(shù)據(jù)庫(kù)中的一個(gè)或多個(gè)表(實(shí)際上是指定了一個(gè)數(shù)據(jù)集)
      * 用你喜歡的格式(YAML、XML等等)來指定預(yù)期數(shù)據(jù)集
      * 斷言這兩個(gè)數(shù)據(jù)集陳述是彼此相等的

      4.數(shù)據(jù)庫(kù)TestCase類強(qiáng)制要求定義一個(gè)基境數(shù)據(jù)集,用它來:

      * 根據(jù)此數(shù)據(jù)集所指定的所有表名,將數(shù)據(jù)庫(kù)中對(duì)應(yīng)表內(nèi)的行全部刪除
      * 將數(shù)據(jù)集內(nèi)數(shù)據(jù)表中的所有行寫入數(shù)據(jù)庫(kù)

      5.三種不同類型:基于文件的、基于查詢的、篩選與組合
      6.Flat XML DataSet(平直XML數(shù)據(jù)集):

      * 一種非常簡(jiǎn)單的XML格式,根節(jié)點(diǎn)為<dataset>,根節(jié)點(diǎn)下每個(gè)標(biāo)簽代表數(shù)據(jù)庫(kù)中的一行數(shù)據(jù),標(biāo)簽就等于表名,而每一個(gè)屬性代表一個(gè)列
      * 在Flat XML DataSet中,要處理NULL值會(huì)非常麻煩,必須保證每個(gè)表的第一行不包含NULL值,只有后繼的那些行才能省略屬性,建議只在不需要NULL值的情況下使用Flat XML DataSet
      * 使用createFlatXmlDataset()創(chuàng)建實(shí)例對(duì)象

      7.XML DataSet(XML數(shù)據(jù)集):

      * 避免了NULL值問題,在根節(jié)點(diǎn)下,可以指定<table>、column、row、value、null標(biāo)簽
      * 使用createXmlDataSet()創(chuàng)建實(shí)例對(duì)象

      8.MySQL XML DataSet(MySQL XML數(shù)據(jù)集):

      * 可以用mysqldump工具來生成這種模式的文件
      * 使用createMySQLXMLDataSet()來創(chuàng)建實(shí)例對(duì)象

      9.YAML DataSet(YAML數(shù)據(jù)集):沒有工廠方法,需要手動(dòng)進(jìn)行實(shí)例化
      10.CSV DataSet(CSV數(shù)據(jù)集):無法指定NULL值
      11.Array DataSet(數(shù)組數(shù)據(jù)集):可以處理NULL值,不需要為斷言提供額外文件
      12.Query(SQL)DataSet(查詢SQL數(shù)據(jù)集)
      13.Database (DB) DataSet(數(shù)據(jù)庫(kù)數(shù)據(jù)集):通過訪問測(cè)試所使用的數(shù)據(jù)庫(kù)鏈接,可以自動(dòng)創(chuàng)建包含數(shù)據(jù)庫(kù)所有表以及其內(nèi)容的DataSet
      14.Replacement DataSet(替換數(shù)據(jù)集):是已有數(shù)據(jù)集的修飾器(decorator),能夠?qū)?shù)據(jù)集中任意列的值替換為其他替代值
      15.DataSet Filter(數(shù)據(jù)集篩選器):為需要包含在子數(shù)據(jù)集中的表和列指定白/黑名單
      16.Composite DataSet(組合數(shù)據(jù)集):能將多個(gè)已存在的數(shù)據(jù)集聚合成單個(gè)數(shù)據(jù)集
      17.假如數(shù)據(jù)庫(kù)中使用了外鍵,必須指定好表的順序,避免外鍵約束失敗

      E.數(shù)據(jù)庫(kù)連接API
      1.getConnection()方法返回的連接接口方法:

      * createDataSet()方法創(chuàng)建一個(gè)Database (DB) DataSet
      * createQueryTable()方法用于創(chuàng)建QueryTable實(shí)例,需要為其指定名稱和所使用的SQL查詢,當(dāng)涉及到結(jié)果/表的斷言這個(gè)方法會(huì)很方便
      * getRowCount()提供了一種方便的方式來取得表中的行數(shù),并且還可以選擇附加一個(gè)WHERE子句來在計(jì)數(shù)前對(duì)數(shù)據(jù)行進(jìn)行過濾


      F.數(shù)據(jù)庫(kù)斷言API
      1.對(duì)表中數(shù)據(jù)行的數(shù)量作出斷言:$this->getConnection()->getRowCount('guestbook')
      2.對(duì)查詢的結(jié)果作出斷言:assertTablesEqual();

      G.常見問題
      1.PHPUnit要求測(cè)試套件開始時(shí)所有數(shù)據(jù)庫(kù)對(duì)象必須全部可用,由于每個(gè)測(cè)試都會(huì)徹底清空數(shù)據(jù)庫(kù),因此無須為每個(gè)測(cè)試重新創(chuàng)建數(shù)據(jù)庫(kù)
      2.只有在基境的清理與建立階段還有斷言檢定時(shí)用到PDO
      3.如果沒有對(duì)TestCase中的getConnection()方法所創(chuàng)建PDO實(shí)例進(jìn)行緩存,那么每個(gè)數(shù)據(jù)庫(kù)測(cè)試都會(huì)增加一個(gè)名多個(gè)數(shù)據(jù)庫(kù)連接

      MyGuestbookTest8_1.php、MyApp_Tests_DatabaseTestCase8_3.php、GuestbookTest8_3.php、8_1Test/、數(shù)組DataSet類

      九、測(cè)試替身
      1.Gerard Meszaros介紹了測(cè)試替身的概念:

      * 有時(shí)候?qū)Ρ粶y(cè)系統(tǒng)(SUT)進(jìn)行測(cè)試是很困難的,因?yàn)樗蕾囉谄渌麩o法在測(cè)試環(huán)境中使用的組件。這有可能是因?yàn)檫@些組件不可用,它們不會(huì)返回測(cè)試所需要的結(jié)果,或者執(zhí)行它們會(huì)有不良副作用。在其他情況下,我們的測(cè)試策略要求對(duì)被測(cè)系統(tǒng)的內(nèi)部行為有更多控制或更多可見性。
      * 如果在編寫測(cè)試時(shí)無法使用(或選擇不使用)實(shí)際的依賴組件(DOC),可以用測(cè)試替身來代替。測(cè)試替身不需要和真正的依賴組件有完全一樣的行為方式;他只需要提供和真正的組件同樣的API即可,這樣被測(cè)系統(tǒng)會(huì)以為它是真正的組件!

      2.PHPUnit提供的createMock($type)和getMockBuilder($type)方法可以在測(cè)試中用來自動(dòng)生成對(duì)象,可以充當(dāng)任意指定原版類型(接口或類名)的測(cè)試替身
      3.createMock()方法直接返回指定類型(接口或類)的測(cè)試替身實(shí)例,替身的創(chuàng)建使用了最佳實(shí)踐的默認(rèn)值(不可執(zhí)行原始類的__construct()和__clone()方法,且不對(duì)傳遞給測(cè)試替身的方法的參數(shù)進(jìn)行克?。?,如果這些默認(rèn)值非你所需,可以用getMockBuilder()方法并使用流暢式接口來定制測(cè)試替身的生成過程
      4.默認(rèn)情況下,原版類的所有方法都會(huì)被替換為只會(huì)返回null的偽實(shí)現(xiàn)(其中不會(huì)調(diào)用原版方法)
      5.局限性:final、private與static,無法對(duì)其進(jìn)行上樁(stub)或模仿(mock)

      A.Stubs(樁件)
      1.將對(duì)象替換為(可選地)返回配置好的返回值的測(cè)試替身的實(shí)踐方法稱為上樁(stubbing)??梢杂脴都╯tub)來“替換掉被測(cè)系統(tǒng)所依賴的實(shí)際組件,這樣測(cè)試就有了對(duì)被測(cè)系統(tǒng)的間接輸入的控制點(diǎn)。這使得測(cè)試能強(qiáng)制安排被測(cè)系統(tǒng)的執(zhí)行路徑,否則被測(cè)系統(tǒng)可能無法執(zhí)行”
      2.僅當(dāng)原始類中不包含名字為“method”的方法時(shí),才能正常運(yùn)行,如果包含,就必須用$stub->expects($this->any())->method('doSomething')->willReturn('foo');
      3.willReturn($value)返回簡(jiǎn)單值,相當(dāng)于will($this->returnValue($value))
      4.有時(shí)想要將(未改變的)方法調(diào)用時(shí)所使用的參數(shù)之一作為樁件的方法的調(diào)用結(jié)果來返回,可以使用returnArgument()
      5.在用流暢式接口進(jìn)行測(cè)試時(shí),讓某個(gè)已上樁的方法返回對(duì)樁件對(duì)象的引用有時(shí)會(huì)很有用,使用returnSelf()
      6.有時(shí)候,上樁的方法需要根據(jù)定義的參數(shù)清單來返回不同的值,可以用returnValueMap()方法將參數(shù)和相應(yīng)的返回值關(guān)聯(lián)起來建立映射
      7.如果上樁的方法需要返回計(jì)算得到的值而不固定值或某個(gè)參數(shù),可以用returnCallback()來讓上樁的方法返回回調(diào)函數(shù)或方法的結(jié)果
      8.相比于建立回調(diào)方法,更簡(jiǎn)單的選擇是直接給出期望返回值的列表,可以用onConsecutiveCalls()方法來做到這個(gè)
      9.除了返回一個(gè)值之外,上樁的方法還能用throwException()拋出一個(gè)異常
      10.可以自行編寫樁件,被廣泛使用的資源是通過單個(gè)外觀(facade)來訪問的,因此很容易就能用樁件替換掉資源
      11.需要上樁的功能往往集中在同一個(gè)對(duì)象中,這就改善了內(nèi)聚度,將功能通過單一且一致的接口呈現(xiàn)出來,就降低了這部分與系統(tǒng)其他部分之間的耦合度

      B.仿件對(duì)象(Mock Object)
      1.將對(duì)象替換為能驗(yàn)證預(yù)期行為(例如斷言某個(gè)方法必會(huì)被調(diào)用)的測(cè)試替身的實(shí)踐方法稱為模仿(mocking)
      2.可以用仿件對(duì)象(mock object)“作為觀察點(diǎn)來核實(shí)被測(cè)系統(tǒng)在測(cè)試中的間接輸出。通常,仿件對(duì)象還需要包括樁件的功能,因?yàn)槿绻麥y(cè)試尚未失敗則仿件對(duì)象需要向被測(cè)系統(tǒng)返回一些值,但是其重點(diǎn)還是在對(duì)間接輸出的核實(shí)上。因此,仿件對(duì)象遠(yuǎn)不止是樁件加斷言,它是以一種根本上完全不同的方式來使用的”
      3.局限性:對(duì)預(yù)期的自動(dòng)校驗(yàn),只會(huì)對(duì)在某個(gè)測(cè)試的作用域內(nèi)生成的仿件對(duì)象進(jìn)行自動(dòng)校驗(yàn)
      4.with()方法可以攜帶任何數(shù)量的參數(shù),對(duì)應(yīng)于被模仿的方法的參數(shù)數(shù)量,可以對(duì)方法的參數(shù)指定更加高等的約束而不僅是簡(jiǎn)單的匹配
      5.withConsecutive()方法可以接受任意多個(gè)數(shù)組作為參數(shù),具體數(shù)量取決于欲測(cè)試的調(diào)用,每個(gè)數(shù)組都是對(duì)被仿方法的相應(yīng)參數(shù)的一組約束,就像with()中那樣
      6.callback()約束用來進(jìn)行更加復(fù)雜的參數(shù)校驗(yàn),此約束的唯一參數(shù)是一個(gè)PHP回調(diào)項(xiàng)(callback),此PHP回調(diào)項(xiàng)接受需要校驗(yàn)的參數(shù)作為其唯一參數(shù),并應(yīng)當(dāng)在參數(shù)通過校驗(yàn)時(shí)返回true,否則返回false
      7.匹配器:

      * any(),當(dāng)被評(píng)定的方法執(zhí)行0次或更多次時(shí)匹配成功
      * never(),當(dāng)被評(píng)定的方法從未執(zhí)行時(shí)匹配成功
      * atLeastOnce(),當(dāng)被評(píng)定的方法執(zhí)行至少一次時(shí)匹配成功
      * once(),當(dāng)被評(píng)定的方法執(zhí)行恰好一次時(shí)匹配成功
      * exactly(int $count),當(dāng)被評(píng)定方法執(zhí)行恰好$count次時(shí)匹配成功
      * at(int $index),當(dāng)被評(píng)定的方法是第$index個(gè)執(zhí)行的方法時(shí)匹配成功


      C.對(duì)特質(zhì)(Trait)與抽象類進(jìn)行模仿
      1.getMockForTrait()方法返回一個(gè)使用了特定特質(zhì)(trait)的仿件對(duì)象,給定特質(zhì)的所有抽象方法將都被模仿
      2.getMockForAbstractClass()方法返回一個(gè)抽象類的仿件對(duì)象,給定抽象類的所有抽象方法都被模仿

      D.對(duì)Web服務(wù)(Web Services)進(jìn)行上樁或模仿
      1.使用getMockFromWsdl(),返回的樁件或者仿件是基于以WSDL描述的web服務(wù)

      E.對(duì)文件系統(tǒng)進(jìn)行模仿
      1.vfsStream是對(duì)虛擬文件系統(tǒng)的流包覆器(stream wrapper),可用于模仿真實(shí)文件系統(tǒng),composer安裝:mikey197/vfsStream
      2.如果不使用諸如vfsStream這樣的虛擬文件系統(tǒng),就無法在隔離外部影響的情況下對(duì)setDirectory()方法進(jìn)行測(cè)試

      SomeClass9_1.php、StubTest9_1.php、SubjectAndObserver9_2.php、SubjectTest9_2.php、TraitClassTest9_3.php、AbstractClassTest9_3.php、Example9_5.php、ExampleTest9_5.php

      十、測(cè)試實(shí)踐
      A.在開發(fā)過程中
      1.當(dāng)需要對(duì)軟件的內(nèi)部結(jié)構(gòu)進(jìn)行更改時(shí),實(shí)際上是要在不影響其可見行為的情況下讓它更加容易理解、更加易于修改,測(cè)試套件對(duì)于重構(gòu)而言是非常寶貴的
      2.有助于改進(jìn)項(xiàng)目的編碼與設(shè)計(jì):

      * 所有單元測(cè)試均正確運(yùn)行
      * 代碼傳達(dá)其設(shè)計(jì)原則
      * 代碼沒有冗余
      * 代碼所包含的類和方法的數(shù)量降至最低


      B.在調(diào)試過程中
      1.壓住沖動(dòng):

      * 確認(rèn)能夠重現(xiàn)此缺陷
      * 在代碼中尋找此缺陷的最小規(guī)模表達(dá)
      * 編寫一個(gè)目前會(huì)失敗而缺陷修復(fù)后將會(huì)成功的自動(dòng)測(cè)試
      * 修復(fù)缺陷

      2.尋找缺陷的最小可靠重現(xiàn)使你有機(jī)會(huì)去真正檢查缺陷的原因。當(dāng)修復(fù)了缺陷之后,所編寫的測(cè)試則有助于提高缺陷真正被修復(fù)的幾率,因?yàn)樾录尤氲臏y(cè)試降低了未來修改代碼時(shí)又破壞此修復(fù)的可能性。而之前所編寫的所有測(cè)試則降低了在不經(jīng)意間導(dǎo)致其他問題的可能性
      3.進(jìn)行單元測(cè)試的好處:

      * 進(jìn)行測(cè)試讓代碼的作者和評(píng)審者對(duì)補(bǔ)丁能夠產(chǎn)生正確的結(jié)果有信心
      * 編寫測(cè)試用例對(duì)開發(fā)者而言是一種很好的發(fā)現(xiàn)邊緣情況的原動(dòng)力
      * 進(jìn)行測(cè)試提供了一種良好的方法來快速捕捉退步(Regression),并且能用來保證退步不會(huì)重復(fù)出現(xiàn)
      * 單元測(cè)試就如何使用API提供了可正常工作的范例,能夠大大幫助文檔編制工作


      十一、代碼覆蓋率分析
      1.計(jì)算機(jī)科學(xué)中所說的代碼覆蓋率是一種用于衡量特定測(cè)試套件對(duì)程序源代碼測(cè)試程度的指標(biāo)。擁有高代碼覆蓋率的程序相較于低代碼低概率的程序而言測(cè)試的更加徹底、包含軟件bug的可能性更低

      A.用于代碼覆蓋率的軟件衡量標(biāo)準(zhǔn)
      1.行覆蓋率(Line Coverage)按單個(gè)可執(zhí)行行是否已執(zhí)行到進(jìn)行計(jì)量
      2.函數(shù)與方法覆蓋率(Function and Method Coverage)按單個(gè)函數(shù)或方法是否已調(diào)用到進(jìn)行計(jì)量。僅當(dāng)函數(shù)或方法的所有可執(zhí)行行全部已覆蓋時(shí)PHP_CodeCoverage才將其視為已覆蓋
      3.類與物質(zhì)覆蓋率(Class and Trait Coverage)按單個(gè)類或特質(zhì)的所有方法是否全部已覆蓋進(jìn)行計(jì)量。僅當(dāng)一個(gè)類或性狀的所有方法全部已覆蓋時(shí)PHP_CodeCoverage才將其視為已覆蓋
      4.Opcode覆蓋率(Opcode Coverage)按函數(shù)或方法對(duì)應(yīng)的每條opcode在運(yùn)行測(cè)試套件時(shí)是否執(zhí)行到進(jìn)行計(jì)量,一行代碼通常會(huì)編譯得到多條opcode,進(jìn)行行覆蓋率計(jì)量時(shí),只要其中任何一條opcode被執(zhí)行就視為此行已覆蓋
      5.分支覆蓋率(Branch Coverage)按控制結(jié)構(gòu)的分支進(jìn)行計(jì)量,測(cè)試套件運(yùn)行時(shí)每個(gè)控制結(jié)構(gòu)的布爾表達(dá)式求值為true和false各自計(jì)為一個(gè)分支
      6.路徑覆蓋率(Path Coverage)按測(cè)試套件運(yùn)行時(shí)函數(shù)或者方法內(nèi)部所經(jīng)歷的執(zhí)行路徑進(jìn)行計(jì)量,一個(gè)執(zhí)行路徑指的是從進(jìn)入函數(shù)或方法一直到離開的過程中經(jīng)過各個(gè)分支的特定序列
      7.變更風(fēng)險(xiǎn)反模式(CRAP)(Change Risk Anti-Patterns (CRAP) Index)基于代碼單元的圈度(cyclomatic complexity)與代碼覆蓋率計(jì)算得出的,不太復(fù)雜并具有恰當(dāng)測(cè)試覆蓋率的代碼將得出較低的CRAP指數(shù)

      B.將文件列入白名單
      1.可以用命令行選項(xiàng)--whitelist或通過配置文件來完成
      2.可以在PHPUnit配置信息中設(shè)置addUncoveredFilesFromWhitelist="true"來將白名單中包含的所有文件全部加入到代碼覆蓋率報(bào)告中

      C.略過代碼塊
      1.一些代碼是無法對(duì)其進(jìn)行測(cè)試的,可以用@codeCoverageIgnore、@codeCoverageIgnoreStart與@codeCoverageIgnoreaEnd標(biāo)注
      2.標(biāo)注將會(huì)計(jì)為已執(zhí)行,并且不會(huì)在代碼覆蓋情況中被高亮標(biāo)記

      D.指明要覆蓋的方法
      1.@covers標(biāo)注可以用在測(cè)試代碼中來指明測(cè)試方法想要對(duì)哪些方法進(jìn)行測(cè)試,如果提供了這個(gè)信息,則只有指定方法的代碼覆蓋率信息會(huì)被統(tǒng)計(jì)
      2.可以用@coversNothing標(biāo)注來指明一個(gè)測(cè)試不

      BankAccountTest11_1.php

      十二、測(cè)試的其他用途
      A.敏捷文檔

      1.極限編程要求群體代碼所有權(quán)(collective code ownership),因此所有開發(fā)者都需要知道整個(gè)系統(tǒng)是如何工作的
      2.PHPUnit的TestDox功能著眼于測(cè)試類及其所有測(cè)試方法的名稱
      3.敏捷文檔也可以以HTML或純文本格式生成,并寫入文件中,用--testdox-html和--testdox-text參數(shù)即可

      B.跨團(tuán)隊(duì)測(cè)試
      1.一旦用測(cè)試將假設(shè)文檔化,你就擁有了測(cè)試

      十三、Logging(日志記錄)
      1.PHPUnit所生成的測(cè)試結(jié)果XML日志文件是基于JUnit task for Apache Ant所使用的XML日志的
      2.PHPUnit所生成的XML格式代碼覆蓋率信息日志記錄不嚴(yán)格地基于Clover,所使用的XML日志的
      3.以易于常人了解(human-readable)的格式生成代碼覆蓋率,輸出到命令行或保存成文本文件

      十四、擴(kuò)展PHPUnit
      1.編寫自定義斷言時(shí),最佳實(shí)踐是遵循PHPUnit自有斷言的實(shí)現(xiàn)方式


      https://github.com/zhangyue0503/php/tree/master/phpunit
      https:///manual/current/zh_cn/phpunit-book.html

        轉(zhuǎn)藏 分享 獻(xiàn)花(0

        0條評(píng)論

        發(fā)表

        請(qǐng)遵守用戶 評(píng)論公約

        類似文章 更多