Chương 13: Kiro Cho Automation Testing
Tóm Tắt
Chương này hướng dẫn automation tester sử dụng Kiro để tạo, quản lý và duy trì test automation suite hiệu quả. Kiro không chỉ giúp viết test code nhanh hơn mà còn đảm bảo test có cấu trúc, dễ maintain và tuân thủ best practices.
Tại Sao Automation Tester Nên Dùng Kiro?
Thách Thức Của Automation Testing
❌ Trước khi có Kiro:
- Viết test code tốn thời gian
- Test suite thiếu cấu trúc
- Khó maintain khi requirements thay đổi
- Test data management phức tạp
- Thiếu documentation cho test cases
✅ Với Kiro:
- Tự động generate test cases từ requirements
- Test framework có cấu trúc rõ ràng
- Dễ dàng update tests khi có thay đổi
- Tự động tạo test data và fixtures
- Documentation được tạo tự động
Lợi Ích Cụ Thể
| Tác Vụ | Không Có Kiro | Với Kiro | Tiết Kiệm |
|---|---|---|---|
| Viết test case | 30 phút | 5 phút | 83% |
| Setup test framework | 2 ngày | 2 giờ | 90% |
| Tạo test data | 1 giờ | 10 phút | 83% |
| Update tests | 1 giờ | 15 phút | 75% |
| Viết documentation | 2 giờ | Tự động | 100% |
Quy Trình Testing Với Kiro
1. Spec-Driven Testing
Thay vì viết test sau khi có code, viết test requirements ngay từ đầu:
Requirements → Test Design → Test Implementation → Execution
Ví dụ: Login Feature
requirements.md:
# Requirements: User Login
## Test Scenarios
### TS-1: Successful Login
**Given** user has valid credentials
**When** user enters correct email and password
**Then** user should be redirected to dashboard
**And** session should be created
**Test Data:**
- Email: test@example.com
- Password: ValidPass123
### TS-2: Invalid Password
**Given** user exists in system
**When** user enters wrong password
**Then** error message "Invalid credentials" should display
**And** user should remain on login page
### TS-3: Account Lockout
**Given** user has failed login 3 times
**When** user tries to login again
**Then** account should be locked for 15 minutes
**And** error message should indicate lockout
## Non-Functional Test Requirements
- Response time: < 2 seconds
- Concurrent users: 100 simultaneous logins
- Security: Password should not appear in logs
2. Test Design Document
design.md:
# Test Design: User Login
## Test Framework
- **Language**: TypeScript
- **Framework**: Playwright
- **Assertion**: Chai
- **Reporting**: Allure
## Test Architecture
### Page Objects
```typescript
class LoginPage {
async navigate(): Promise<void>
async enterEmail(email: string): Promise<void>
async enterPassword(password: string): Promise<void>
async clickLogin(): Promise<void>
async getErrorMessage(): Promise<string>
}
class DashboardPage {
async isDisplayed(): Promise<boolean>
async getUserName(): Promise<string>
}
Test Data Management
interface TestUser {
email: string;
password: string;
role: 'admin' | 'user';
}
class TestDataFactory {
static createValidUser(): TestUser
static createInvalidUser(): TestUser
}
Test Utilities
class TestHelper {
static async waitForPageLoad(): Promise<void>
static async takeScreenshot(name: string): Promise<void>
static async clearTestData(): Promise<void>
}
Test Execution Strategy
- Smoke Tests: Run on every commit
- Regression Tests: Run nightly
- Performance Tests: Run weekly
Test Environment
- Dev: https://dev.example.com
- Staging: https://staging.example.com
- Production: Manual trigger only ```
3. Test Implementation Tasks
tasks.md:
# Test Implementation Plan
- [ ] 1. Setup test framework
- [ ] 1.1 Initialize Playwright project
- [ ] 1.2 Configure TypeScript
- [ ] 1.3 Setup Allure reporting
- [ ] 1.4 Create base test class
- [ ] 2. Implement Page Objects
- [ ] 2.1 Create LoginPage class
- [ ] 2.2 Create DashboardPage class
- [ ] 2.3 Add page object methods
- [ ] 2.4 Add element locators
- [ ] 3. Create test data management
- [ ] 3.1 Create TestUser interface
- [ ] 3.2 Implement TestDataFactory
- [ ] 3.3 Create test fixtures
- [ ] 3.4 Setup database seeding
- [ ] 4. Write test cases
- [ ] 4.1 Test successful login (TS-1)
- [ ] 4.2 Test invalid password (TS-2)
- [ ] 4.3 Test account lockout (TS-3)
- [ ] 4.4 Add assertions and validations
- [ ] 5. Setup CI/CD integration
- [ ] 5.1 Create GitHub Actions workflow
- [ ] 5.2 Configure test execution
- [ ] 5.3 Setup test reporting
- [ ] 5.4 Add notifications
Tạo Test Framework Với Kiro
Bước 1: Tạo Spec Cho Test Framework
# Trong Kiro Chat
Tạo spec cho test automation framework sử dụng Playwright và TypeScript.
Framework cần hỗ trợ:
- Page Object Model
- Test data management
- Screenshot on failure
- Allure reporting
- Parallel execution
Bước 2: Kiro Generate Test Structure
Kiro sẽ tạo cấu trúc:
tests/
├── config/
│ ├── playwright.config.ts
│ └── test.config.ts
├── pages/
│ ├── BasePage.ts
│ ├── LoginPage.ts
│ └── DashboardPage.ts
├── fixtures/
│ ├── users.json
│ └── testData.ts
├── helpers/
│ ├── TestHelper.ts
│ └── ApiHelper.ts
├── specs/
│ ├── login.spec.ts
│ └── dashboard.spec.ts
└── reports/
└── allure-results/
Bước 3: Implement Tests Với Autopilot
# Click "Start Tasks" trong Specs panel
# Kiro sẽ tự động:
1. Setup Playwright
2. Tạo Page Objects
3. Viết test cases
4. Configure reporting
5. Setup CI/CD
Steering Files Cho Testing
.kiro/steering/testing.md
# Testing Guidelines
## Test Framework Standards
- Use Playwright for E2E tests
- Use Jest for unit tests
- Use Supertest for API tests
- All tests must use TypeScript
## Test Structure
- Follow AAA pattern (Arrange, Act, Assert)
- Use Page Object Model for UI tests
- One assertion per test when possible
- Clear and descriptive test names
## Naming Conventions
```typescript
// Test files: *.spec.ts
// Page objects: *Page.ts
// Test data: *.fixture.ts
// Helpers: *Helper.ts
Test Data
- Never use production data
- Use factories for test data creation
- Clean up test data after each test
- Store sensitive data in environment variables
Assertions
// ✅ Good
expect(loginPage.errorMessage).toBe('Invalid credentials');
// ❌ Bad
expect(loginPage.errorMessage).toBeTruthy();
Error Handling
- Take screenshot on test failure
- Log detailed error messages
- Capture network requests on failure
- Save page HTML on failure
Performance
- Tests should complete in < 30 seconds
- Use parallel execution when possible
- Mock external dependencies
- Reuse browser contexts
CI/CD Integration
- Run smoke tests on every PR
- Run full regression nightly
- Fail build if tests fail
- Generate and publish test reports
Documentation
- Every test should have a description
- Link tests to requirements
- Document test data setup
- Maintain test execution guide ```
Ví Dụ: Tạo API Test Suite
Prompt Cho Kiro
Tạo spec cho API test suite với các yêu cầu:
1. Test REST API endpoints:
- GET /api/users
- POST /api/users
- PUT /api/users/:id
- DELETE /api/users/:id
2. Test cases cần cover:
- Happy path scenarios
- Validation errors
- Authentication/Authorization
- Rate limiting
- Error handling
3. Framework:
- Jest + Supertest
- TypeScript
- Test data factories
- API response schemas validation
4. Reporting:
- Jest HTML reporter
- Coverage report (>80%)
Kiro Sẽ Generate
1. Test Structure:
// tests/api/users.spec.ts
describe('Users API', () => {
describe('GET /api/users', () => {
it('should return list of users', async () => {
const response = await request(app)
.get('/api/users')
.set('Authorization', `Bearer ${validToken}`);
expect(response.status).toBe(200);
expect(response.body).toHaveProperty('users');
expect(Array.isArray(response.body.users)).toBe(true);
});
it('should return 401 without auth token', async () => {
const response = await request(app).get('/api/users');
expect(response.status).toBe(401);
expect(response.body.error).toBe('Unauthorized');
});
});
describe('POST /api/users', () => {
it('should create new user with valid data', async () => {
const newUser = UserFactory.create();
const response = await request(app)
.post('/api/users')
.set('Authorization', `Bearer ${adminToken}`)
.send(newUser);
expect(response.status).toBe(201);
expect(response.body).toMatchSchema(UserSchema);
expect(response.body.email).toBe(newUser.email);
});
it('should return 400 with invalid email', async () => {
const invalidUser = { email: 'invalid', password: 'pass123' };
const response = await request(app)
.post('/api/users')
.set('Authorization', `Bearer ${adminToken}`)
.send(invalidUser);
expect(response.status).toBe(400);
expect(response.body.errors).toContain('Invalid email format');
});
});
});
2. Test Data Factory:
// tests/factories/UserFactory.ts
import { faker } from '@faker-js/faker';
export class UserFactory {
static create(overrides?: Partial<User>): User {
return {
email: faker.internet.email(),
password: faker.internet.password({ length: 12 }),
firstName: faker.person.firstName(),
lastName: faker.person.lastName(),
role: 'user',
...overrides
};
}
static createAdmin(): User {
return this.create({ role: 'admin' });
}
static createBatch(count: number): User[] {
return Array.from({ length: count }, () => this.create());
}
}
3. Schema Validation:
// tests/schemas/UserSchema.ts
export const UserSchema = {
type: 'object',
required: ['id', 'email', 'firstName', 'lastName'],
properties: {
id: { type: 'string', format: 'uuid' },
email: { type: 'string', format: 'email' },
firstName: { type: 'string', minLength: 1 },
lastName: { type: 'string', minLength: 1 },
role: { type: 'string', enum: ['user', 'admin'] },
createdAt: { type: 'string', format: 'date-time' }
}
};
Hooks Cho Testing
Auto-Run Tests On Save
// .kiro/hooks/run-tests-on-save.json
{
"name": "Run Tests On Save",
"version": "1.0.0",
"when": {
"type": "fileEdited",
"patterns": ["src/**/*.ts", "tests/**/*.spec.ts"]
},
"then": {
"type": "askAgent",
"prompt": "Run tests related to the changed file and report results"
}
}
Generate Test On New Feature
// .kiro/hooks/generate-test.json
{
"name": "Generate Test For New Feature",
"version": "1.0.0",
"when": {
"type": "fileCreated",
"patterns": ["src/**/*.ts"]
},
"then": {
"type": "askAgent",
"prompt": "Generate corresponding test file with basic test cases for the new file"
}
}
Update Tests On Spec Change
// .kiro/hooks/update-tests.json
{
"name": "Update Tests On Spec Change",
"version": "1.0.0",
"when": {
"type": "fileEdited",
"patterns": [".kiro/specs/**/requirements.md"]
},
"then": {
"type": "askAgent",
"prompt": "Review requirement changes and update corresponding test cases"
}
}
Best Practices Cho Automation Tester
1. Test Pyramid
/\
/E2E\ ← Ít tests, chậm, brittle
/------\
/ API \ ← Vừa phải
/----------\
/ Unit \ ← Nhiều tests, nhanh, stable
/--------------\
Với Kiro:
# .kiro/steering/test-strategy.md
## Test Distribution
- Unit tests: 70% (fast, isolated)
- API tests: 20% (integration)
- E2E tests: 10% (critical user flows only)
## When to Write Each Type
- Unit: Business logic, utilities, helpers
- API: Endpoint contracts, data validation
- E2E: Critical user journeys, smoke tests
2. Test Data Management
// ✅ Good: Use factories
const user = UserFactory.create({ role: 'admin' });
// ❌ Bad: Hardcoded data
const user = { email: 'test@test.com', password: '123456' };
Kiro giúp:
"Tạo test data factory cho User model với các methods:
- create(): tạo user ngẫu nhiên
- createAdmin(): tạo admin user
- createBatch(n): tạo n users
- withRole(role): tạo user với role cụ thể"
3. Page Object Pattern
// ✅ Good: Page Object
class LoginPage {
private emailInput = 'input[name="email"]';
private passwordInput = 'input[name="password"]';
private loginButton = 'button[type="submit"]';
async login(email: string, password: string) {
await this.page.fill(this.emailInput, email);
await this.page.fill(this.passwordInput, password);
await this.page.click(this.loginButton);
}
}
// Test
test('should login successfully', async () => {
await loginPage.login('user@test.com', 'pass123');
expect(await dashboardPage.isDisplayed()).toBe(true);
});
// ❌ Bad: Direct selectors in test
test('should login successfully', async () => {
await page.fill('input[name="email"]', 'user@test.com');
await page.fill('input[name="password"]', 'pass123');
await page.click('button[type="submit"]');
});
4. Assertions
// ✅ Good: Specific assertions
expect(response.status).toBe(200);
expect(response.body.email).toBe('test@example.com');
expect(response.body.users).toHaveLength(5);
// ❌ Bad: Generic assertions
expect(response.status).toBeTruthy();
expect(response.body).toBeDefined();
5. Test Independence
// ✅ Good: Each test is independent
describe('User CRUD', () => {
beforeEach(async () => {
await TestHelper.clearDatabase();
await TestHelper.seedTestData();
});
test('should create user', async () => {
// Test logic
});
test('should update user', async () => {
// Test logic
});
});
// ❌ Bad: Tests depend on each other
test('1. should create user', async () => {
userId = await createUser();
});
test('2. should update user', async () => {
await updateUser(userId); // Depends on test 1
});
Troubleshooting
Kiro Generate Tests Không Đúng
Vấn đề: Tests không cover đủ scenarios
Giải pháp:
# Trong requirements.md, bổ sung:
## Test Coverage Requirements
- Happy path: All main flows
- Error cases: All validation errors
- Edge cases: Boundary values, empty inputs
- Security: Authentication, authorization
- Performance: Response time, load testing
## Test Scenarios
[List chi tiết từng scenario]
Tests Quá Brittle
Vấn đề: Tests fail khi UI thay đổi nhỏ
Giải pháp:
# .kiro/steering/testing.md
## Locator Strategy
- Prefer data-testid over CSS selectors
- Use semantic HTML roles
- Avoid XPath when possible
```typescript
// ✅ Good
await page.click('[data-testid="login-button"]');
await page.getByRole('button', { name: 'Login' }).click();
// ❌ Bad
await page.click('div > div > button.btn-primary');
Test Data Conflicts
Vấn đề: Tests fail vì data conflicts
Giải pháp:
// Use unique data per test
const uniqueEmail = `test-${Date.now()}@example.com`;
// Or use test isolation
beforeEach(async () => {
await db.truncate('users');
});
Kết Luận
Kiro là công cụ mạnh mẽ cho automation tester, giúp:
- Tạo test framework nhanh chóng
- Generate test cases từ requirements
- Maintain tests dễ dàng
- Tự động hóa quy trình testing
Đầu tư thời gian học Kiro sẽ giúp bạn tăng năng suất testing lên 3-5 lần.
Chương tiếp theo: Tạo Test Framework với Kiro
Bài viết được viết bằng AI 🚀