Laravel 單元測試實戰(2)- 編寫實際功能並讓程式碼測試透過

yyy123456發表於2022-09-23

Laravel 單元測試實戰(2)- 編寫實際功能並讓程式碼測試透過

github 專案地址

git clone https://gitee.com/three_kingdoms_of_zhang/unit_test_practice.git
composer install
git checkout v2.0

程式碼是完整的,包括遷移,模型類,和全部功能。

service 實際編寫,完成功能。

class ServiceOrder
{

    /**
     * 根據購物車資訊,和已有的優惠券,查詢最優惠的一張優惠券。
     *
     * @param array $shopping_cart 前端傳來的商品資訊。
     * // 購物車格式
     * $shopping_cart = [
     *            [
     *                'goods_id' => 1,
     *                'count' => 3,
     *            ],
     *            [
     *                'goods_id' => 2,
     *                'count' => 1,
     *            ],
     *            [
     *                'goods_id' => 3,
     *                'count' => 2,
     *            ],
     *        ];
     *
     * @param Collection $goods_records 自己查的資料庫資訊,商品的。
     * @param Collection $user_coupon_records 自己查的使用者優惠券資訊。
     *
     * @return [
     *    'saved_money' => 0, //優惠券自身的等價金額
     *    'user_coupon_record' => [ //優惠券記錄,或者null
     *        'id' => 4,
     *        'type' => 2,
     *        'coupon_value' => 0.9,
     *        'condition_money' => 50,
     *    ]
     * ]
     */
    public function find_user_coupon_from_shopping_cart(array $shopping_cart,Collection $goods_records,
                                                        Collection $user_coupon_records):array
    {
        $total = $this->calculate_total_price( $shopping_cart, $goods_records );
        $finded_user_coupon = $user_coupon_records
            ->filter(function ($user_coupon)use($total){ // 先根據總價過濾一部分
                return $user_coupon['condition_money'] < $total;
            })->map(function($user_coupon)use($total){ //開始計算節省金額
                if ($user_coupon['type']==1) {
                    $user_coupon['saved_money'] = $user_coupon['coupon_value'] ;
                }
                if ($user_coupon['type']==2) {
                    $user_coupon['saved_money'] = $total * (1- $user_coupon['coupon_value']) ;
                }
                return $user_coupon;
            })->sortByDesc(function ($user_coupon) { //根據節省金額倒序排
                return $user_coupon['saved_money'];
            })->first();                             //取出第一個優惠券。
        if ($finded_user_coupon) {
            return [
                 'saved_money' => $finded_user_coupon['saved_money'], //優惠券自身的等價金額
                 'user_coupon_record' => [ //這個對應表中的一條記錄。
                     'id' => $finded_user_coupon['id'],
                     'type' => $finded_user_coupon['type'],
                     'coupon_value' => $finded_user_coupon['coupon_value'],
                     'coupon_name' => $finded_user_coupon['coupon_name'],
                 ]
              ];
        }
        return [
            'saved_money' => 0,
            'user_coupon_record' => null,
        ];
    }

    // 算總價
    private function calculate_total_price(array $shopping_cart,Collection $goods_records):float
    {
        $total=0;
        foreach( $shopping_cart as $shop_count){
            $count = $shop_count['count'];
            $unit_price=0;
            foreach ( $goods_records as $goods ){
                if ( $goods['id'] == $shop_count['goods_id'] ){
                    $unit_price = $goods['price'];
                    break;
                }
            }
            if (!$unit_price) {
                throw new \Exception('引數錯誤');
            }
            $total += $count * $unit_price;
        }
        return $total;
    }



}

同時,發現了原先的單元測試程式碼要改一句話。斷言節省金額的程式碼。

原先,
$this->assertEquals($result['saved_money'], $result_expect['saved_money'];

應改成:
$this->assertEqualsWithDelta($result['saved_money'], $result_expect['saved_money'],0.02);

執行單元測試

./vendor/bin/phpunit ./tests/Unit/ServiceOrderTest.php

會顯示測試透過。

總結:

把功能實際寫好,然後再次執行單元測試程式碼,這次透過了。
同時發現,單元測試必須修改,因為涉及到小數運算,無法精確,所以需要忽略一定的精度。
實際上,這介面就已經完成了。

但是,後面再寫一個整合測試。帶上資料庫,徹底驗證該程式碼的正確性。
另外,這裡寫的單元測試,覆蓋的邏輯比較少,還需要測試邊界條件,比如優惠券列表為空等情況。

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

相關文章