[AI] Kiro Cho Automation Testing

Posted by : on

Category : ai   kiro


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 🚀


About Nguyen Chung
Nguyen Chung

Hi I am Nguyen Chung, an Automation Tester.

Email : ndchungict@gmail.com

Website : https://ndchungict.github.io

About Nguyen Chung

Hi, my name is Nguyen Duc Chung. Nice to see you!