iT邦幫忙

2022 iThome 鐵人賽

DAY 13
0

Medium 清新閱讀版連結

今天讓我們看看幾個重要的 PHPUnit @ Annotation 吧!

所謂的 PHPUnit @ Annotation,是指在測試案例函數前的 PHP Doc 區塊,PHPUnit 提供開發者引用的 @ Annotation。PHPUnit 提供的 @ Annotation 大約有 20+ 個,今天會和大家介紹最常用的幾個。

測試目標函數

首先,大家請先閱讀以下程式碼,後續的@ Annotation 範例皆是以此為測試目標:

  • app/Services/TestService.php

    <?php
    
    namespace App\Services;
    
    use Exception;
    
    class TestService
    {
        /**
         * @throws Exception
         */
        public function calculateBmi(float $height, float $weight): float
        {
            if ($weight <= 0 || $height <= 0) {
                throw new Exception('Invalid input!', 1);
            }
    
            return $weight / ($height * $height);
        }
    }
    

Annotation 介紹

  1. @test

    • 介紹:當測試程式碼中的函數之 PHP Doc 區塊有引用此 Annotation 時,PHPUnit方會將此函數當成測試案例函數執行。

      說到這邊,可能有些讀者會覺得奇怪,過去兩週的文章中,有很多範例測試函數都沒有使用 @test,為什麼仍可以正常執行?
      原因是,除了測試程式碼中的有引用 @test 的函數 PHPUnit 會當成測試案例函數來執行,若一個測試程式碼中的函數,是以 test 為開頭,如 testCanCalcuateBmi(),那麼 PHPUnit 也會把它當測試案例函數來執行。

    • 範例:

      <?php
      
      namespace Tests\Feature;
      
      use App\Services\TestService;
      use Exception;
      use Tests\TestCase;
      
      class ExceptionTest extends TestCase
      {
          /**
           * @test
           */
          public function canCalcuateBmi()
          {
              $service = app(TestService::class);
      
              $this->expectException(Exception::class);
      
              $bmiActual = $service->calculateBmi(64.0, 1.6);
              $bmiExpected = 64.0/(1.6^2);
      
              $this->assertEquals($bmiExpected, $bmiActual);
          }
      
      		public function testCanCalcuateBmi()
          {
              $service = app(TestService::class);
      
              $this->expectException(Exception::class);
      
              $bmiActual = $service->calculateBmi(64.0, 1.6);
              $bmiExpected = 64.0/(1.6^2);
      
              $this->assertEquals($bmiExpected, $bmiActual);
          }
      
      		public function canCalcuateBmi2()
          {
              $service = app(TestService::class);
      
              $this->expectException(Exception::class);
      
              $bmiActual = $service->calculateBmi(64.0, 1.6);
              $bmiExpected = 64.0/(1.6^2);
      
              $this->assertEquals($bmiExpected, $bmiActual);
          }
      }
      

      以上程式碼中,canCalcuateBmi()testCanCalcuateBmi() 兩函數都會被執行,canCalcuateBmi2() 則不會。

  2. @depends

    • 介紹:當測試程式碼中的函數之 PHP Doc 區塊有引用此 Annotation ,則 PHPUnit 會確認其依賴的測試案例函數有驗證通過,方會執行當前的測試案例涵數。

    • 範例:

      <?php
      
      namespace Tests\Feature;
      
      use App\Services\TestService;
      use Exception;
      use Tests\TestCase;
      
      class ExceptionTest extends TestCase
      {
          public function testCanCalcuateBmi()
          {
              $service = app(TestService::class);
      
              $this->expectException(Exception::class);
      
              $bmiActual = $service->calculateBmi(64.0, 1.6);
              $bmiExpected = 64.0/(1.6^2);
      
              $this->assertEquals($bmiExpected, $bmiActual);
          }
      
          /**
           * @depends testCanCalcuateBmi
           */
          public function testCanThrowExceptionWhenInvaliHeight()
          {
              $service = app(TestService::class);
      
              $this->expectException(Exception::class);
      
              $service->calculateBmi(0.0, 1.0);
          }
      }
      

      以上程式碼中,當 testCanCalcuateBmi() 驗證通過時,testCanThrowExceptionWhenInvaliHeight() 才會被執行;當testCanCalcuateBmi() 測試失敗時,testCanThrowExceptionWhenInvaliHeight()不會被執行。

  3. @group

    • 介紹:顧名思義,此 Annotation 可以將多個測試案例函數分組。

    • 範例:

      <?php
      
      namespace Tests\Feature;
      
      use App\Services\TestService;
      use Exception;
      use Tests\TestCase;
      
      class ExceptionTest extends TestCase
      {
          /**
      		 * @group BMI
           */
          public function testCanCalcuateBmi()
          {
              $service = app(TestService::class);
      
              $this->expectException(Exception::class);
      
              $bmiActual = $service->calculateBmi(64.0, 1.6);
              $bmiExpected = 64.0/(1.6^2);
      
              $this->assertEquals($bmiExpected, $bmiActual);
          }
      
          /**
           * @group BMI
           */
          public function testCanThrowExceptionWhenInvaliHeight()
          {
              $service = app(TestService::class);
      
              $this->expectException(Exception::class);
      
              $service->calculateBmi(0.0, 1.0);
          }
      }
      

      以上程式碼中,當我們在命令列執行 ./vendor/bin/phpunit --group=BMI 時, testCanCalcuateBmi()testCanThrowExceptionWhenInvaliHeight() 都會被執行。除此之外,一個測試案例函數可以被歸類在多個 @group 喔!

  4. @testWith

    • 介紹:此 Annotation 可以讓我們對同一個測試案例函數,執行一組以上資料組的測試驗證。

    • 範例:

      <?php
      
      namespace Tests\Feature;
      
      use App\Services\TestService;
      use Exception;
      use Tests\TestCase;
      
      class ExceptionTest extends TestCase
      {
          /**
      		 * @testWith [0.0, 1.0]
           *           [1.0, 0.0]
           *           [0.0, 0.0]
           */
          public function testCanThrowExceptionWhenInvalidData(float $height, float $weight)
          {
              $service = app(TestService::class);
      
              $this->expectException(Exception::class);
      
              $service->calculateBmi($height, $weight);
          }
      }
      

      以上程式碼中, testCanThrowExceptionWhenInvalidData() 會被執行3次:

      • testCanThrowExceptionWhenInvalidData(0.0, 1.0)
      • testCanThrowExceptionWhenInvalidData(1.0, 0.0)
      • testCanThrowExceptionWhenInvalidData(0.0, 0.0)
  5. @dataProvider

    • 介紹:此 Annotation 與 @testWith 類似,但使用方式比較特別,姑且讓我們保留到下一篇文章再做介紹。 ?

以上就是今天的介紹,大家可以多演練一下唷!

明天來為大家介紹 setUp()、tearDown()、Data Provider 這三個特殊函數!

參考資料


上一篇
例外測試
下一篇
setUp()、tearDown()、Data Provider
系列文
自動化測試大作戰31
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言