基於 Laravel 框架的 phpunit 單元測試爬坑記錄

小煩發表於2017-09-19

基於 Laravel 框架的 phpunit 單元測試爬坑記錄

1、單元測試的目錄結構

  • 測試檔案一般位於專案根目錄下的 tests 資料夾或者 models 下的專案中的 tests 資料夾。

  • 在命令列中執行以下命令:

    
    php artisan make:test DemoTest //可以生成 DemoTest.php 測試檔案

//這種方式生成的測試檔案建立在專案根目錄下的 tests/Feature

> - 在命令列中執行以下命令:

phpunit //會執行所有 test 方法`
phpunit tests/Feature/BackendTest.php //會執行所有 BackendTest.php 裡的 test 方法

---
2、測試程式碼編寫
1. 帶入引數請求訪問介面
1. 獲取返回值斷言
舉個例子:
---

class AccountTest extends TestCase
//所有測試類必須基於TestCase
{
/**

  • 測試使用者資訊詳情頁介面
  • @return mixed
    */
    //所有測試方法命名,必須以 test 小寫開頭命名
    //(或者在註釋中寫明標註 @test )
    public function testuserinfo_detail()
    {
    $response = $this->get('http://ideabuy.xin.cn/api/userinfo-detail',$this->authHeader)
    // $this->assertEquals('ture',$response->getcontent());
    //當下面斷言失敗時,將這行程式碼取消註釋,將下面註釋,上面程式碼最後加上分號,再次執行,即可看到報錯具體資訊。
    ->assertJsonFragment([
    'msg'=>'查詢成功',
    //斷言返回的JSON值中包含一個 msg:‘查詢成功’ 的物件
    ]);
    }
    }

介紹幾個介面訪問方式

  • GET 請求
get($uri, array $headers = []);
  • POST 請求
post($uri, array $data = [], array $headers = []);
  • JSON 請求
    json('POST', $uri, $data, $headers);
  • CALL 請求
    call('PUT', $uri, $data, [], [], $server);

獲取介面返回值方法

$response->getcontent();
$response->getOriginalContent();

獲取介面返回值方法

簡單列幾個常見的斷言方法,具體更多的斷言方法--點此跳轉連結

  • $this->assertJsonFragment($params)
    // 判斷返回的JSON數值裡是否包含$params
    當返回值有 json 格式的 msg 資訊
$this->assertJsonFragment([
                'msg'=>'頭像修改成功',
            ]);
  • $this->assertJsonStructure($params);
    // 判斷返回的JSON資料裡是否包含$params資料結構
    當返回值中不存在 msg 時(例如使用者詳情查出來基本為 data 時)可以用來判斷是否存在資料。
$this->assertJsonStructure([
                'data'=>[],
            ]);
  • $this->assertEquals(1,$params);
    // 斷返回值是否與$params相同
$this->assertEquals(1, $result['code']);
  • assertResponseOk();
    // 斷言客戶端返回的響應狀態碼是否是200
$this->assertResponseOk();

2、測試程式碼編寫
由於大部分介面都做了使用者登入的判斷,所以在對介面進行測試的時候需要帶上使用者登入的資訊(token+版本資訊)。

  • 獲取token的時候(即模擬登陸的時候--userlogin方法)如果報 ==data== 錯誤,先檢查一下本地環境是不是需要全拼路由才能訪問介面。
    例:
$response = $this->get('http://ideabuy.xin.cn/backend/constype-list', $this->authHeader)
  • 如果token可以列印的情況下,還報錯。檢查一下 setup 方法是否新增了重新整理語句。
    即:
    例:
$this->refreshApplication();
  • 下面的程式碼舉了一個userlogin登入的操作,backend登入可以仿照下面操作,在 Common 裡的方法中新增一個adminlogin,然後繼承這個類去呼叫登入後的token
    嗯,我還是貼程式碼吧:
    ==路徑:test/common/ApiTestCase.php==
   public function adminLogin($params = [])
    {
        $response = $this->post(
            'http://ideabuy.xin.cn/backend/admin-login',
            $params
        );

        $admins = $response->getOriginalContent();

        return $admins;
    }

==路徑:test/BackendTest.php==

  public function setUp()
   {
        parent::setUp();

        $this->params = $this->readyApiParams();
        $admin = $this->adminLogin($this->params['login']);
        $this->admin = $admin;
        $this->authHeader = $this->headers($admin);

        $this->refreshApplication();
    }
  • 接下來在你寫的test方法裡的頭部資訊就可以直接$this->authHeader 進行呼叫了!
    類似於這樣:
    $response = $this->get('http://ideabuy.xin.cn/backend/order-detail?order_id=282',  $this->authHeader)

附上登入用例程式碼:

==路徑:test/common/ApiTestCase.php==

<?php

namespace Modules\Api\Tests\Common;

use Tests\TestCase;

/**
 * Class ApiTestCase
 * @package Modules\Api\Tests\Common
 */
class ApiTestCase extends TestCase
{
    /**
     * User login
     * @param array $params
     * @return mixed
     */
    public function userLogin($params = [])
    {
        $response = $this->post(
        #路由看個人環境配置是否需要加上 http://ideabuy.xin.cn
            'http://ideabuy.xin.cn/api/user-login',
            $params,
        #呼叫下面拼接token的方法
            $this->headers()
        );

        $users = $response->getOriginalContent();

        return $users;
    }

    /**
     * Setting request header
     * @param null $user
     * @param array $addition
     * @return array
     */
    protected function headers($user = null, $addition = [])
    {
        #新增版本號頭部資訊
        $headers = ['Accept' => 'application/vnd.ideabuy.v1+json'];
        #拼接 token
        if (!is_null($user)) {
            $headers['Authorization'] = 'Bearer '.$user['data']['token'];
        }

        if($addition){
            $headers = array_merge($headers,$addition);
        }

        return $headers;
    }

}

==路徑:test/AccountTest.php==

<?php

namespace Modules\Api\Tests;

use Modules\Api\Tests\Common\ApiTestCase;

class AccountTest extends ApiTestCase
{
    public $authHeader;
    public $params;
    public $data;
    public $user;

    /**
     * ready for data & params
     */
    public function setUp()
    {
        #每個test方法之前都會呼叫一次這個方法
        parent::setUp();

        $this->params = $this->readyApiParams();
        /** Get auth info include token  */
        #呼叫使用者登入的操作
        $user = $this->userLogin($this->params['login']);
        $this->user = $user;
        #獲取使用者 token
        $this->authHeader = $this->headers($user);

        #重新整理應用。該操作由TestCase的setup()方法自動呼叫,不然會使用過期的token
        $this->refreshApplication();
    }

    /**
     * Ready for test params
     */
    protected function readyApiParams()
    {
        #這個方法用來放test裡需要的引數
        $params = [];

        /** login params for test **/

        $login = [
            'user_mobile' => '13777979098',
            'user_password' => 'a12345678'
        ];
        $params['login'] = $login;

        /** register user params for test **/

        $register = [
            'user_mobile' => '13777979098',
            'user_password' => 'a12345678',
            'confirm_password' => 'a12345678',
            'code' => '1234'
        ];
        $params['register'] = $register;

        /** setting user paypassword params for test **/

        $payPassword = ['pay_password' => 'b11111111'];
        $params['payPassword'] = $payPassword;

        return $params;
    }

    /**
     * Clean  test data
     */
    protected function cleanData()
    {
        //todo logic data
        //Artisan::call('migrate:reset');
    }

    /**
     * this is case for user login
     */
    public function testUserLogin()
    {
        $this->assertEquals(1, $this->user['code']);
    }

    /**
     * This is case for setting pay password
     * @test
     */
    public function SetPayPassword()
    {

        $response = $this->post(
            'http://ideabuy.xin.cn/api/user-setpaypwd',
                $this->params['payPassword'],
                #獲取token
                $this->authHeader
        );

        $result = $response->getOriginalContent();
        #getOriginalContent()是將返回值轉成陣列,getcontent()是直接將物件返回
        $this->assertEquals(1, $result['code']);

    }

    /**
     * Drop something test data
     */
    public function tearDown()
    {
        $this->cleanData();

        parent::tearDown();

    }

}

歡迎大家給意見和補充。

本作品採用《CC 協議》,轉載必須註明作者和本文連結

相關文章