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 協議》,轉載必須註明作者和本文連結