AI viết Test Case: Có đáng tin không? Phân tích thực tế
Phân tích khả năng AI viết unit test, integration test và test case - Khi nào nên dùng, khi nào không, với ví dụ Laravel/PHPUnit thực tế.
Giới thiệu
Viết test là công việc mà nhiều developer… né tránh. Boring, repetitive, và “tốn thời gian”. Khi AI tools hứa hẹn có thể generate test cases tự động, câu hỏi đặt ra là: AI viết test có đáng tin không?
Bài viết này sẽ phân tích thực tế khả năng AI viết tests, dựa trên kinh nghiệm sử dụng với Laravel/PHPUnit - bao gồm cả những gì AI làm tốt và những gì cần human review.
AI có thể viết test gì?
Unit Tests - AI làm tốt ⭐⭐⭐⭐
Unit tests cho isolated functions là thế mạnh của AI. Logic đơn giản, input/output rõ ràng.
Ví dụ prompt:
Viết unit tests cho function sau:
public function calculateDiscount(float $price, int $percentage): float
{
if ($percentage < 0 || $percentage > 100) {
throw new InvalidArgumentException('Percentage must be 0-100');
}
return $price - ($price * $percentage / 100);
}
Cần cover:
- Happy path
- Edge cases
- Error scenarios
AI Output:
class DiscountCalculatorTest extends TestCase
{
private DiscountCalculator $calculator;
protected function setUp(): void
{
parent::setUp();
$this->calculator = new DiscountCalculator();
}
// Happy Path Tests
/** @test */
public function it_calculates_10_percent_discount(): void
{
$result = $this->calculator->calculateDiscount(100.00, 10);
$this->assertEquals(90.00, $result);
}
/** @test */
public function it_calculates_50_percent_discount(): void
{
$result = $this->calculator->calculateDiscount(200.00, 50);
$this->assertEquals(100.00, $result);
}
// Edge Cases
/** @test */
public function it_returns_same_price_for_zero_discount(): void
{
$result = $this->calculator->calculateDiscount(100.00, 0);
$this->assertEquals(100.00, $result);
}
/** @test */
public function it_returns_zero_for_100_percent_discount(): void
{
$result = $this->calculator->calculateDiscount(100.00, 100);
$this->assertEquals(0.00, $result);
}
/** @test */
public function it_handles_decimal_prices(): void
{
$result = $this->calculator->calculateDiscount(99.99, 10);
$this->assertEquals(89.991, $result);
}
// Error Scenarios
/** @test */
public function it_throws_exception_for_negative_percentage(): void
{
$this->expectException(InvalidArgumentException::class);
$this->expectExceptionMessage('Percentage must be 0-100');
$this->calculator->calculateDiscount(100.00, -10);
}
/** @test */
public function it_throws_exception_for_percentage_over_100(): void
{
$this->expectException(InvalidArgumentException::class);
$this->calculator->calculateDiscount(100.00, 150);
}
}
Đánh giá: Code này usable immediately. AI hiểu boundary cases và generate comprehensive coverage.
Integration Tests - AI làm được nhưng cần review ⭐⭐⭐
Integration tests phức tạp hơn vì cần hiểu database state, relationships, và side effects.
Prompt:
Viết integration test cho OrderService::createOrder()
public function createOrder(array $items, User $user): Order
{
return DB::transaction(function () use ($items, $user) {
$order = Order::create([
'user_id' => $user->id,
'status' => 'pending',
'total' => collect($items)->sum('subtotal'),
]);
foreach ($items as $item) {
$order->items()->create($item);
$product = Product::find($item['product_id']);
$product->decrement('stock', $item['quantity']);
}
OrderCreated::dispatch($order);
return $order;
});
}
AI Output (cần review):
class OrderServiceTest extends TestCase
{
use RefreshDatabase;
/** @test */
public function it_creates_order_with_items(): void
{
// Arrange
$user = User::factory()->create();
$product1 = Product::factory()->create(['stock' => 100, 'price' => 50]);
$product2 = Product::factory()->create(['stock' => 50, 'price' => 30]);
$items = [
[
'product_id' => $product1->id,
'quantity' => 2,
'price' => $product1->price,
'subtotal' => 100,
],
[
'product_id' => $product2->id,
'quantity' => 1,
'price' => $product2->price,
'subtotal' => 30,
],
];
// Act
$order = app(OrderService::class)->createOrder($items, $user);
// Assert
$this->assertDatabaseHas('orders', [
'id' => $order->id,
'user_id' => $user->id,
'status' => 'pending',
'total' => 130,
]);
$this->assertCount(2, $order->items);
// Stock decremented
$this->assertEquals(98, $product1->fresh()->stock);
$this->assertEquals(49, $product2->fresh()->stock);
}
/** @test */
public function it_dispatches_order_created_event(): void
{
Event::fake([OrderCreated::class]);
$user = User::factory()->create();
$product = Product::factory()->create(['stock' => 10]);
$items = [
['product_id' => $product->id, 'quantity' => 1, 'price' => 50, 'subtotal' => 50],
];
$order = app(OrderService::class)->createOrder($items, $user);
Event::assertDispatched(OrderCreated::class, function ($event) use ($order) {
return $event->order->id === $order->id;
});
}
/** @test */
public function it_rolls_back_on_failure(): void
{
$user = User::factory()->create();
$product = Product::factory()->create(['stock' => 1]); // Only 1 in stock
$items = [
['product_id' => $product->id, 'quantity' => 5, 'price' => 50, 'subtotal' => 250],
];
// ⚠️ AI assumption - actual behavior depends on implementation
$this->expectException(InsufficientStockException::class);
app(OrderService::class)->createOrder($items, $user);
// Order should not exist
$this->assertDatabaseMissing('orders', ['user_id' => $user->id]);
}
}
Vấn đề cần review:
- Test
it_rolls_back_on_failure- AI assume có exception, nhưng original code không throw - Cần thêm test cho concurrent stock update
- Missing test cho empty items array
Feature/E2E Tests - Cần human nhiều ⭐⭐
Feature tests testing full HTTP request flow - AI có thể generate skeleton nhưng cần nhiều adjustments.
// AI thường generate tests kiểu này
/** @test */
public function user_can_place_order(): void
{
$user = User::factory()->create();
$product = Product::factory()->create();
$response = $this->actingAs($user)
->postJson('/api/orders', [
'items' => [
['product_id' => $product->id, 'quantity' => 1],
],
]);
$response->assertStatus(201)
->assertJsonStructure([
'data' => ['id', 'status', 'total', 'items'],
]);
}
Vấn đề: AI không biết actual API response structure, authentication middleware, validation rules của project cụ thể.
Những gì AI làm KHÔNG TỐT
1. Edge Cases dựa trên Business Logic
AI không biết business rules specific của project:
// AI không biết rule: "VIP users get free shipping over $100"
// Sẽ không generate test cho case này
2. Concurrency & Race Conditions
// AI hiếm khi suggest tests cho:
/** @test */
public function it_handles_concurrent_stock_updates(): void
{
$product = Product::factory()->create(['stock' => 1]);
// Simulate 2 users trying to buy the last item
$promises = [
async(fn() => $this->service->purchase($product, 1)),
async(fn() => $this->service->purchase($product, 1)),
];
// Only one should succeed
}
3. Security Tests
// AI generate nhưng thường thiếu cases:
// - SQL Injection vectors
// - XSS payloads
// - Authorization bypass attempts
// - Rate limiting
4. Performance Tests
AI không generate performance benchmarks hoặc load tests.
Best Practices khi dùng AI viết tests
✅ Nên làm
- Cung cấp context đầy đủ
Đây là Laravel 11 project.
Testing với PHPUnit.
Sử dụng RefreshDatabase trait.
Factory đã có sẵn cho User, Product, Order.
- Yêu cầu specific coverage
Cần tests cho:
- Validation errors (422)
- Unauthorized access (403)
- Not found (404)
- Successful creation (201)
-
Review và adjust
- Run tests ngay sau generate
- Fix failing tests manually
- Thêm edge cases mà AI miss
-
Dùng AI để generate skeleton, human fill details
❌ Không nên làm
- Trust blindly - Tests có thể pass nhưng không test đúng behavior
- Skip review - AI có thể assert wrong values
- Expect AI biết business logic - Phải describe rõ
- Generate và commit - Luôn run tests locally trước
Workflow đề xuất
1. Viết code mới
2. AI generate test skeleton
3. Review và adjust tests
4. Run tests, fix failures
5. Add edge cases manually
6. Run coverage report
7. Fill gaps
Metrics từ thực tế
Sau 6 tháng sử dụng AI generate tests:
| Metric | Kết quả |
|---|---|
| Tests usable immediately | ~40% |
| Tests cần minor fixes | ~35% |
| Tests cần rewrite | ~25% |
| Time saved (estimate) | 50-60% |
| Bugs caught by AI tests | Lower than manual |
Kết luận
AI viết test có đáng tin không?
Trả lời: Có, nhưng với điều kiện.
✅ AI tốt cho:
- Unit tests đơn giản
- Boilerplate test structure
- Happy path coverage
- Speeding up repetitive work
❌ AI chưa tốt cho:
- Complex business logic tests
- Security tests
- Performance tests
- Edge cases specific to your domain
Lời khuyên cuối:
Hãy coi AI như junior developer viết tests - output cần review, nhưng tiết kiệm thời gian đáng kể so với viết từ đầu.
Công thức tối ưu: AI generate 60% + Human review 20% + Human edge cases 20% = Balanced coverage + Saved time.
Thử Thách Kiến Thức Lịch Sử?
Khám phá hàng trăm câu hỏi trắc nghiệm lịch sử thú vị tại HistoQuiz. Vừa học vừa chơi, nâng cao kiến thức ngay hôm nay!