-
Notifications
You must be signed in to change notification settings - Fork 59
[SangCT] Do homework #26
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
[SangCT] Do homework #26
Conversation
| /** | ||
| * A basic unit test example. | ||
| * | ||
| * @return void | ||
| */ | ||
| public function test__contruct() | ||
| { | ||
| $controller = new ProductController($this->productServiceMock); | ||
|
|
||
| $this->assertInstanceOf(ProductController::class, $controller); | ||
|
|
||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Test constructor có ý nghĩa gì không em?
|
|
||
| } | ||
|
|
||
| public function test_index() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Test index là test cái gì, tên test case nên thể hiện được mục đích của test case
Mục 1 trong checklist:
- [1] Self-describing test method](https://sun-unit-test-training.github.io/php-testing-guideline/06-checklist/#1-self-describing-test-method)
| $request = $this->mock(CheckoutRequest::class); | ||
| $request->shouldReceive('input') | ||
| ->once() | ||
| ->with('total_products') | ||
| ->andReturn($input); | ||
|
|
||
| $this->productServiceMock->shouldReceive('calculateDiscount') | ||
| ->with($input) | ||
| ->once() | ||
| ->andReturn(7); | ||
|
|
||
| $controller = new ProductController($this->productServiceMock); | ||
|
|
||
| $this->assertInstanceOf(JsonResponse::class, $controller->checkout($request)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Cái này viết theo cách dùng HTTP tests như ở test_index được không? Sao case này lại viết cách khác nhỉ?
| public function test_rules() | ||
| { | ||
| $request = new CheckoutRequest(); | ||
|
|
||
| $this->assertSame([ | ||
| 'total_products' => 'required|array', | ||
| 'total_products.*' => 'nullable|integer|min:0', | ||
| ], $request->rules()); | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Viết như này ko sai, nhưng không khuyến khích
https://sun-unit-test-training.github.io/php-testing-guideline/laravel/03-controller/#unit-test
| /** | ||
| * @param $totalProducts | ||
| * @param $expectedValue | ||
| * @dataProvider provideValidTotalProductsData | ||
| * */ | ||
| public function test_calculate_discount_with_valid_data($totalProducts, $expectedValue) | ||
| { | ||
| $discount = $this->productService->calculateDiscount($totalProducts); | ||
| $this->assertEquals($expectedValue, $discount); | ||
| } | ||
|
|
||
| public function provideValidTotalProductsData() | ||
| { | ||
| return [ | ||
| [ | ||
| [ | ||
| 1 => 2, | ||
| 2 => 2, | ||
| 3 => 2, | ||
| ], 5 | ||
| ], | ||
| [ | ||
| [ | ||
| 1 => 0, | ||
| 2 => 4, | ||
| 3 => 4, | ||
| ], 7 | ||
| ], | ||
| [ | ||
| [ | ||
| 1 => 2, | ||
| 2 => 3, | ||
| 3 => 3, | ||
| ], 12 | ||
| ], | ||
| ]; | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Viết như này đọc khá khó hiểu, ít nhất nên đặt tên cho từng dataset hoặc là tách ra các case riêng biệt
- Input chỉ bao gồm các số, nhìn như các số ngẫu nhiên, không thể hiện được điều kiện input đầu vào là gì => Các key input nó đã được đặt tên bằng const trong class Product thì nên sử dụng ở đây
Với cả thiếu case nhé?
Anh thấy bài này có thể chia case theo kết quả mong muốn thì sẽ rất dễ sinh input, có 4 kết quả mong muốn:
- Exception => invalid data
- Discount = 5 => only cravat white discount
- Discount = 7 => only total quantity discout
- Discount = 12 => both discounts
Hoặc có thể bám theo lý thuyết C1
if ($cravat < 0 || $whiteShirt < 0 || $others < 0) {
// (1)
throw new InvalidArgumentException();
} // else (2)
if ($cravat > 0 && $whiteShirt > 0) {
// (3)
$discount = self::CRAVAT_WHITE_SHIRT_DISCOUNT;
} // else (4)
if (($cravat + $whiteShirt + $others) >= self::TOTAL_PRODUCT_TO_DISCOUNT) {
// (5)
$discount += self::QUANTITY_DISCOUNT;
} // else (6)- (1) => End
- (2) (3) (5) => End
- ...
Và nên thêm 1 case để test cận cho điều kiện >= 7, vì dấu >= và dấu > thường rất dễ nhầm
tuanpt-0634
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
A đã comment gợi ý cho 1 vài bài, nên đọc lại guideline, checklist và refactor cả những phần khác
|
|
||
| $controller = new ProductController($this->productServiceMock); | ||
|
|
||
| $this->assertInstanceOf(JsonResponse::class, $controller->checkout($request)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Đoạn này nên có thêm assert cho
->json(['discount' => $discount]);
Để xem xem là người dùng có truyền discount đúng cái trả về từ service không
| $this->assertEquals($expectedValue, $discount); | ||
| } | ||
|
|
||
| public function provideValidTotalProductsData() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ở đây thiếu miss mất 1 case.
Giả sử các trường hợp dưới đây không tồn tại thì ra sao?
$totalProducts[Product::CRAVAT_TYPE]
$totalProducts[Product::OTHER_TYPE]
$totalProducts[Product::WHITE_SHIRT_TYPE]
Ngoài thì thì a cũng để ý các trương logic so sánh >= hiện tại anh chỉ đang test các trường hợp > nhưng đối với các trường hợp = thì đang không test
|
|
||
| public function test_index() | ||
| { | ||
| $this->calendarServiceMock->shouldReceive('getDateClass') |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Trong controller này có logic, nên phải làm sao test đưuọc cả logic đấy. Muốn test được logic đấy thì có 2 cách
1 là cái mock này không nên chỉ shouldReceive và andReturn luôn.
Mình nên làm để biết thêm là cái method getDateClass gọi bao nhiêu lần và những tham số truyền vào là gì
2 là
$response->assertViewHas('calendars'); thì mình phải assert xem cả cái data của nó nữa
| * */ | ||
| public function test_handle_discount($detailOrder, $expectedValue) | ||
| { | ||
| $resultOrder = $this->orderService->handleDiscount($detailOrder); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Trong provider này nên thêm có 1 case nữa check độ chính xác tới 2 chữ số thập phân vì cái round nó có thêm tham số thứ 2 là 2
$infoBill['price'] = round(($detailOrder['price'] * 80) / 100, 2);
Cái này nice to have 😄
Ngoài ra nữa thì anh để ý các logic >= nhá
| $this->assertEquals($expectedValue, $time); | ||
| } | ||
|
|
||
| public function provideData() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ở đây sẽ có 1 case, là giả sử không truyền vào has_watch thì kết quả sẽ ra sao.
Tất nhiên là không truyền vào has_watch thì default nó là false thì nó sẽ trùng 1 trong các số test của mình. Nhưng về cơ bản thì vẫn phải có case là không truyền vào cái gì cả
Purpose/Notes
Write UnitTest Module 3->7
Screenshot
Checklist (*)