前言
近期嘗試各種 AI 開發工具(Cursor、Claude CLI、Gemini Code) 越來越篤定測試和 AI 開發流程絕對是相輔相成的存在。本文摸索怎麼樣的流程能夠最大化與 AI 配合產出。
小試身手
透過 Vite 創建一個簡單的 Vue 單頁應用,並請 AI Agent 替預設範例元件 HelloWorld.vue 撰寫測試:Write test for HelloWorld using @vue/test-utils。
<script setup lang="ts">import { ref } from 'vue'
defineProps<{ msg: string }>()
const count = ref(0)</script>
<template> <h1>{{ msg }}</h1>
<div class="card"> <button type="button" @click="count++">count is {{ count }}</button> <p> Edit <code>components/HelloWorld.vue</code> to test HMR </p> </div>
<p> Check out <a href="https://vuejs.org/guide/quick-start.html#local" target="_blank" >create-vue</a >, the official Vue + Vite starter </p> <p> Learn more about IDE Support for Vue in the <a href="https://vuejs.org/guide/scaling-up/tooling.html#ide-support" target="_blank" >Vue Docs Scaling up Guide</a >. </p> <p class="read-the-docs">Click on the Vite and Vue logos to learn more</p></template>
<style scoped>.read-the-docs { color: #888;}</style>import { describe, it, expect } from 'vitest'import { mount } from '@vue/test-utils'import HelloWorld from './HelloWorld.vue'
describe('HelloWorld', () => { it('renders the message prop correctly', () => { const message = 'Hello Vue!' const wrapper = mount(HelloWorld, { props: { msg: message } })
expect(wrapper.find('h1').text()).toBe(message) })
it('displays initial count as 0', () => { const wrapper = mount(HelloWorld, { props: { msg: 'Test Message' } })
expect(wrapper.find('button').text()).toBe('count is 0') })
it('increments count when button is clicked', async () => { const wrapper = mount(HelloWorld, { props: { msg: 'Test Message' } })
const button = wrapper.find('button')
// Click the button await button.trigger('click')
// Check if count increased to 1 expect(button.text()).toBe('count is 1')
// Click again await button.trigger('click')
// Check if count increased to 2 expect(button.text()).toBe('count is 2') })
it('renders the edit instruction text', () => { const wrapper = mount(HelloWorld, { props: { msg: 'Test Message' } })
expect(wrapper.text()).toContain('Edit') expect(wrapper.text()).toContain('components/HelloWorld.vue') expect(wrapper.text()).toContain('to test HMR') })
it('renders the create-vue link with correct attributes', () => { const wrapper = mount(HelloWorld, { props: { msg: 'Test Message' } })
const createVueLink = wrapper.find('a[href="https://vuejs.org/guide/quick-start.html#local"]')
expect(createVueLink.exists()).toBe(true) expect(createVueLink.text()).toBe('create-vue') expect(createVueLink.attributes('target')).toBe('_blank') })
it('renders the Vue Docs link with correct attributes', () => { const wrapper = mount(HelloWorld, { props: { msg: 'Test Message' } })
const vueDocsLink = wrapper.find('a[href="https://vuejs.org/guide/scaling-up/tooling.html#ide-support"]')
expect(vueDocsLink.exists()).toBe(true) expect(vueDocsLink.text()).toBe('Vue Docs Scaling up Guide') expect(vueDocsLink.attributes('target')).toBe('_blank') })
it('renders the read-the-docs paragraph with correct class', () => { const wrapper = mount(HelloWorld, { props: { msg: 'Test Message' } })
const readTheDocs = wrapper.find('p.read-the-docs')
expect(readTheDocs.exists()).toBe(true) expect(readTheDocs.text()).toBe('Click on the Vite and Vue logos to learn more') })
it('has the correct CSS class for read-the-docs', () => { const wrapper = mount(HelloWorld, { props: { msg: 'Test Message' } })
const readTheDocs = wrapper.find('.read-the-docs') expect(readTheDocs.exists()).toBe(true) })
it('renders all expected elements', () => { const wrapper = mount(HelloWorld, { props: { msg: 'Test Message' } })
// Check for main elements expect(wrapper.find('h1').exists()).toBe(true) expect(wrapper.find('.card').exists()).toBe(true) expect(wrapper.find('button').exists()).toBe(true) expect(wrapper.find('code').exists()).toBe(true)
// Check for all paragraphs const paragraphs = wrapper.findAll('p') expect(paragraphs).toHaveLength(4) })})可以發現僅需片刻 AI 就能根據文件配置相關套件與根據現有完成所有測試案例,雖然有些許不足的地方但大致能用,AI 開發問題不在於熟悉套件的操作或是撰寫程式的速度,而是「思考周全」與「傳達清楚目的」。
經驗豐富的測試者會知道如何撰寫更穩定有價值的測試:
- 撰寫有意義的測試案例
- 不要針對程式的私有狀態或方法去測試
- 透過自製的屬性搭配選取器如:
data-test="add-button"應對測試的變化
很多最佳實踐都可以在官方文件中找到,但不告知 AI 它就不會知道。所以務必針對 AI 提供充分的上下文,可以是官方提倡的最佳實踐、經驗豐富開發者的建議或常犯的錯誤。
測試案例驅動 AI 開發
既然 AI 測試寫得又快又好,那透過我們自己描述測試案例作為開發文件不是很棒的做法嗎?