当前位置: 首页 > article >正文

测试环境搭建指南:从零开始构建完善的测试体系

测试环境搭建指南从零开始构建完善的测试体系前言各位前端小伙伴不知道你们有没有这样的经历在自己电脑上测试好好的一到CI环境就各种失败。我曾经因为测试环境和生产环境不一致导致线上出现了一个严重bug。后来我意识到测试环境的一致性至关重要测试环境搭建步骤1. 安装依赖# 安装Vitest测试框架 npm install -D vitest # 安装Vue测试工具 npm install -D vue/test-utils # 安装Playwright端到端测试 npm install -D playwright/test npx playwright install # 安装Mock工具 npm install -D msw2. 配置Vitest创建vitest.config.tsimport { defineConfig } from vitest/config import vue from vitejs/plugin-vue import { resolve } from path export default defineConfig({ plugins: [vue()], test: { environment: jsdom, globals: true, coverage: { provider: v8, reporter: [text, json, html], exclude: [node_modules/, dist/, *.config.ts] }, setupFiles: [./vitest.setup.ts] }, resolve: { alias: { : resolve(__dirname, src) } } })3. 创建测试入口文件创建vitest.setup.tsimport { expect } from vitest import matchers from testing-library/jest-dom/matchers expect.extend(matchers) import { setupServer } from msw/node import { handlers } from ./mocks/handlers const server setupServer(...handlers) beforeAll(() server.listen({ onUnhandledRequest: error })) afterEach(() server.resetHandlers()) afterAll(() server.close())4. 配置Playwright创建playwright.config.tsimport { defineConfig, devices } from playwright/test export default defineConfig({ testDir: ./tests, fullyParallel: true, forbidOnly: !!process.env.CI, retries: process.env.CI ? 2 : 0, workers: process.env.CI ? 1 : undefined, reporter: html, use: { baseURL: http://localhost:5173, trace: on-first-retry, }, projects: [ { name: chromium, use: { ...devices[Desktop Chrome] }, }, { name: firefox, use: { ...devices[Desktop Firefox] }, }, { name: webkit, use: { ...devices[Desktop Safari] }, }, { name: Mobile Chrome, use: { ...devices[Pixel 5] }, }, { name: Mobile Safari, use: { ...devices[iPhone 14] }, }, ], webServer: { command: npm run dev, url: http://localhost:5173, reuseExistingServer: !process.env.CI, } })5. 创建Mock数据创建mocks/handlers.tsimport { http, HttpResponse } from msw export const handlers [ http.get(/api/users, () { return HttpResponse.json([ { id: 1, name: John Doe, email: johnexample.com }, { id: 2, name: Jane Smith, email: janeexample.com } ]) }), http.post(/api/login, async ({ request }) { const data await request.json() if (data.email adminexample.com data.password password) { return HttpResponse.json({ token: mock-jwt-token, user: { id: 1, name: Admin } }) } return HttpResponse.json({ error: Invalid credentials }, { status: 401 }) }) ]测试目录结构src/ ├── components/ │ ├── Button.vue │ └── Button.test.ts ├── utils/ │ ├── calculator.ts │ └── calculator.test.ts ├── api/ │ ├── users.ts │ └── users.test.ts └── App.vue tests/ ├── login.spec.ts ├── dashboard.spec.ts └── checkout.spec.ts mocks/ └── handlers.ts vitest.config.ts playwright.config.ts vitest.setup.tsCI/CD集成GitHub Actions配置创建.github/workflows/test.ymlname: Test on: push: branches: [ main ] pull_request: branches: [ main ] jobs: test: runs-on: ubuntu-latest steps: - uses: actions/checkoutv4 - name: Use Node.js uses: actions/setup-nodev4 with: node-version: 20 - name: Install dependencies run: npm ci - name: Run unit tests run: npm run test:unit - name: Run end-to-end tests run: npm run test:e2e - name: Upload coverage report uses: actions/upload-artifactv4 with: name: coverage-report path: coverage/GitLab CI配置创建.gitlab-ci.ymlstages: - test unit-test: stage: test image: node:20 script: - npm ci - npm run test:unit artifacts: reports: junit: coverage/junit.xml e2e-test: stage: test image: mcr.microsoft.com/playwright:v1.40.0-jammy script: - npm ci - npm run test:e2e测试脚本配置{ scripts: { test:unit: vitest run, test:unit:watch: vitest, test:unit:coverage: vitest run --coverage, test:e2e: playwright test, test:e2e:headed: playwright test --headed, test:e2e:debug: playwright test --debug, test: npm run test:unit npm run test:e2e } }测试环境隔离使用环境变量// src/config.ts export const config { apiUrl: import.meta.env.VITE_API_URL || http://localhost:3000, timeout: Number(import.meta.env.VITE_TIMEOUT) || 5000 } // .env.test VITE_API_URLhttp://localhost:3000 VITE_TIMEOUT10000数据库隔离// tests/utils/database.ts import { PrismaClient } from prisma/client const prisma new PrismaClient() export async function setupTestDatabase() { await prisma.user.deleteMany({}) await prisma.post.deleteMany({}) } export async function teardownTestDatabase() { await prisma.$disconnect() } export async function createTestUser(data: PartialUser) { return prisma.user.create({ data: { email: data.email || testexample.com, name: data.name || Test User, ...data } }) }测试辅助工具Testing Libraryimport { render, screen, fireEvent } from testing-library/vue import Button from ./Button.vue test(button renders correctly, () { render(Button, { props: { text: Click me } }) const button screen.getByRole(button, { name: /click me/i }) expect(button).toBeInTheDocument() fireEvent.click(button) })Vue Test Utilsimport { mount } from vue/test-utils import Counter from ./Counter.vue test(counter increments, async () { const wrapper mount(Counter) expect(wrapper.find(.count).text()).toBe(0) await wrapper.find(button).trigger(click) expect(wrapper.find(.count).text()).toBe(1) })测试环境调试使用debug模式# Vitest调试 npx vitest --inspect-brk # Playwright调试 npx playwright test --debug生成测试报告# 单元测试报告 npx vitest run --coverage open coverage/index.html # 端到端测试报告 npx playwright test open playwright-report/index.html常见问题解决问题1测试环境与生产环境不一致解决方案使用相同的Node.js版本和依赖版本# 使用.nvmrc echo 20.10.0 .nvmrc # 使用package-lock.json锁定依赖 npm ci问题2测试依赖外部服务解决方案使用Mock替代真实服务// 使用MSW拦截API请求 vi.mock(axios, () ({ default: vi.fn(() Promise.resolve({ data: mockData })) }))问题3测试运行缓慢解决方案并行运行测试避免依赖外部服务使用更快的测试框架如Vitest替代Jest// vitest.config.ts export default defineConfig({ test: { maxWorkers: 4 } })问题4测试不稳定解决方案确保测试隔离避免测试间依赖使用自动等待// ✅ 使用自动等待 await expect(page.locator(textSuccess)).toBeVisible() // ❌ 避免硬编码等待 await page.waitForTimeout(1000)总结搭建一个完善的测试环境需要选择合适的测试框架Vitest用于单元测试Playwright用于端到端测试配置测试环境设置JSDOM环境、Mock服务、覆盖率报告集成CI/CD确保每次代码提交都自动运行测试保持环境一致使用环境变量、锁定依赖版本调试和优化使用调试工具、优化测试性能现在开始构建你的测试环境吧一个好的测试环境可以让你的开发更加高效和可靠。最后一句忠告测试环境不是一劳永逸的需要持续维护和优化

相关文章:

测试环境搭建指南:从零开始构建完善的测试体系

测试环境搭建指南:从零开始构建完善的测试体系 前言 各位前端小伙伴,不知道你们有没有这样的经历:在自己电脑上测试好好的,一到CI环境就各种失败。 我曾经因为测试环境和生产环境不一致,导致线上出现了一个严重bug。后…...

终极指南:如何在Mac上快速安装配置DistroAV网络视频插件 [特殊字符]

终极指南:如何在Mac上快速安装配置DistroAV网络视频插件 🚀 【免费下载链接】obs-ndi DistroAV (formerly OBS-NDI): NDI integration for OBS Studio 项目地址: https://gitcode.com/gh_mirrors/ob/obs-ndi 想要在多台电脑之间轻松传输高质量的音…...

LinkedIn Liger Kernel:移动设备内核定制与性能优化实战

1. 项目概述:一个面向移动设备的开源内核探索如果你在移动设备开发、嵌入式系统或者内核研究的圈子里待过一段时间,大概率听说过或者接触过“Liger Kernel”这个名字。它不是一个商业产品,而是一个在GitHub上由LinkedIn开源并维护的Android内…...

RAG和向量索引

为特定用例设计代理时,需要确保语言模型已建立基础并使用与用户所需内容相关的事实信息。 虽然语言模型针对大量数据进行了训练,但它们可能无权访问你想要向用户提供的知识。 若要确保代理基于特定数据提供准确且特定于域的响应,可使用检索增…...

做电力仪器选显示屏踩坑3年,终于摸透这四个选型标准

我是电力仪器设备厂的生产测试主管,干这行快7年了,前前后后负责过继保测试仪、变比测试仪、互感器校验仪等七八款产品的配件选型,光显示屏就换过四家供应商,踩过强电磁下跳数、低温黑屏、交期拖垮项目的坑,直到用上恒域…...

10个免费Illustrator脚本:让你的设计效率提升300%的终极工具集

10个免费Illustrator脚本:让你的设计效率提升300%的终极工具集 【免费下载链接】illustrator-scripts Adobe Illustrator scripts 项目地址: https://gitcode.com/gh_mirrors/il/illustrator-scripts 如果你经常使用Adobe Illustrator进行设计工作&#xff0…...

系统稳定性测试利器:Roast烤机工具原理与实践指南

1. 项目概述:一个为“烤”而生的开源工具最近在折腾一些自动化任务时,发现了一个挺有意思的开源项目,叫sumleo/roast。光看名字,你可能会联想到“烤肉”,但在程序员的世界里,这个“roast”可不是让你去烧烤…...

Windows 一键部署 OpenClaw 教程|5 分钟搭建本地 AI 智能体,轻松搞定复杂配置

OpenClaw 2.7.1 接入阿里云百炼超详细图文教程 📋 前置准备 本地已安装并能正常运行 OpenClaw 2.7.1 WindowsOpenClaw 顶部 Gateway 保持在线状态拥有可正常登录的阿里云账号网络可正常访问阿里云百炼控制台: https://bailian.console.aliyun.com/cn-be…...

滑动窗口(数组)

作用滑动窗口&#xff1a;求连续满足条件的最短子数组代码模板int left 0; int right;//外层循环扩展右边界&#xff0c;内层循环扩展左边界 for (right 0; right < n; right) {//获取当前考虑的元素while (left < right && check()) {//区间[left,right]不符合…...

Claude Markdown增强资源库:提升AI文档生成质量与效率

1. 项目概述&#xff1a;为什么我们需要一个“Claude Markdown 增强”资源库&#xff1f; 如果你和我一样&#xff0c;是 Claude 的深度用户&#xff0c;并且经常用它来辅助编程、撰写文档或整理知识&#xff0c;那你一定遇到过这个痛点&#xff1a;Claude 输出的 Markdown 代…...

Python 爬虫进阶技巧:JSON 数据多层嵌套解析取值技巧

前言 在现代网络数据采集场景中,JSON(JavaScript Object Notation)已成为前后端数据交互的核心格式,绝大多数动态网页、API 接口均采用多层嵌套 JSON 结构传输数据。对于爬虫开发者而言,基础的 JSON 取值仅能应对简单数据结构,而面对深度嵌套、数组嵌套、混合嵌套等复杂…...

自动化知识库构建工具:从多源聚合到持续部署的工程实践

1. 项目概述&#xff1a;一个面向开发者的自动化知识库构建工具最近在折腾个人知识管理和团队文档沉淀时&#xff0c;发现了一个挺有意思的开源项目&#xff0c;叫devp1/autopedia。乍一看这个名字&#xff0c;可能会联想到“自动百科全书”&#xff0c;但它的定位其实更精准&a…...

claw-installer:构建自动化部署脚本的工程实践与设计哲学

1. 项目概述与核心价值最近在折腾一个挺有意思的开源项目&#xff0c;叫claw-installer。这名字乍一看有点抽象&#xff0c;但如果你对自动化部署、特别是那些需要处理复杂依赖和配置的应用感兴趣&#xff0c;那这个工具很可能就是你一直在找的“瑞士军刀”。简单来说&#xff…...

Python 爬虫进阶技巧:定时爬虫任务实现无人值守采集

前言 常规爬虫多依赖手动触发脚本运行,单次采集完成后需人工二次启动,无法满足日常周期性数据监控、行情抓取、资讯同步、业务台账定时归档等常态化采集需求。搭建可自主调度、自动启停、周期循环的定时爬虫任务,脱离人工干预实现无人值守全自动采集,是爬虫从临时脚本走向…...

终极解决方案:3分钟搞定百度网盘提取码的免费自动化工具

终极解决方案&#xff1a;3分钟搞定百度网盘提取码的免费自动化工具 【免费下载链接】baidupankey 项目地址: https://gitcode.com/gh_mirrors/ba/baidupankey 还在为百度网盘资源下载卡在提取码这一步而烦恼吗&#xff1f;每次遇到需要密码的分享链接&#xff0c;都要…...

免费豆包大模型API代理部署指南:原理、实战与安全实践

1. 项目概述&#xff1a;一个免费且强大的大模型API代理 最近在折腾大语言模型应用开发的朋友&#xff0c;估计都绕不开一个核心痛点&#xff1a;API调用成本。无论是OpenAI的GPT系列&#xff0c;还是国内外的其他主流模型&#xff0c;按Token计费的模式在频繁调试和原型验证阶…...

游戏交易税、年龄锁与拒付账单:APP出海全球合规风暴

上周&#xff0c;监管与平台的合规重拳&#xff0c;密集落在了游戏交易、未成年人保护和支付链条上。几项变化直接且锋利&#xff0c;对出海游戏厂商而言&#xff0c;已不再是远期预警&#xff0c;而是迫在眉睫的执行项。 美国州级监管&#xff1a;直指游戏内购与停服责任 科…...

基于苏格拉底式提问的LLM深度推理:从概念澄清到工程实践

1. 项目概述&#xff1a;当AI学会“苏格拉底式提问”最近在探索如何让大语言模型&#xff08;LLM&#xff09;的推理能力更上一层楼时&#xff0c;我遇到了一个非常有意思的开源项目&#xff1a;jumasheff/socratic-rules。这个名字本身就充满了哲学与技术碰撞的火花——“苏格…...

AI系统行为治理:构建确定性护栏与运行时安全控制

1. 项目概述&#xff1a;为AI系统构建确定性的行为护栏如果你正在构建一个会“动手”的AI应用——无论是能帮你写代码的智能助手&#xff0c;还是能操作数据库的自动化流程&#xff0c;甚至是部署在物理设备上的机器人——那么你迟早会面临一个核心问题&#xff1a;如何确保它只…...

AMD Carrizo架构解析:SoC集成与HSA异构计算如何重塑移动处理器

1. 从“胶水粘合”到“原生融合”&#xff1a;Carrizo与Carrizo-L的架构革命2014年底&#xff0c;当AMD在新加坡的“计算的未来”活动上拿出Carrizo和Carrizo-L这两颗芯片时&#xff0c;现场的反应可能比预想的要平静一些。毕竟&#xff0c;对于习惯了每年“挤牙膏”式升级的行…...

AgenticTime:为AI智能体设计的时间推理引擎与.atime文件格式详解

1. 项目概述&#xff1a;为AI智能体赋予时间感知能力如果你用过Claude、GPT或者任何基于大语言模型的AI助手&#xff0c;肯定遇到过这样的场景&#xff1a;你告诉它“周五前要完成API评审”&#xff0c;它当时答应得好好的&#xff0c;但当你隔天再问“我这周有什么要紧事”时&…...

传统企业XaaS转型实战:从商业模式重构到运营模型落地

1. 云服务转型的十字路口&#xff1a;从“卖盒子”到“卖服务”的本质跨越在过去的十几年里&#xff0c;我亲眼见证了“云”从一个时髦的技术概念&#xff0c;演变为驱动几乎所有行业数字化转型的核心引擎。无论是初创公司还是百年老店&#xff0c;都在谈论上云、用云、管云。但…...

2026最新版|音频格式转换超详细全攻略:8种方法和避坑指南

你是否有过这样的经历——从录音笔导出的WAV文件体积太大无法发送&#xff0c;下载的FLAC无损音乐在车上无法播放&#xff0c;或者视频剪辑时发现音频格式不被软件识别&#xff1f;这些场景都会用到音频格式转换。本文基于2026年最新可用工具&#xff0c;把8种转换方法极度细化…...

小白必看!3个月从零基础到AI大模型工程师,独家学习路线助你轻松上岸!收藏不迷路!

本文分享了作者从计算机小白成功转行AI大模型工程师的亲身经历&#xff0c;并提供了独家学习路线。文章指出企业更看重能实际应用Python搭建AI智能体、用Java迭代项目的技能&#xff0c;而非死磕算法和公式。作者建议先掌握Python基础、建立对大模型的基本认知、磨练Prompt技巧…...

用 C 语言函数表实现通信传输层抽象

用 C 语言函数表实现通信传输层抽象 在嵌入式 Linux 或工业控制类程序中&#xff0c;一个应用经常需要同时接入多种通信链路&#xff0c;例如 UDP、串口、CAN、TCP 或 Unix Socket。 这些链路的底层实现差异很大&#xff1a; UDP 基于 socket串口基于 tty 设备CAN 基于 SocketC…...

【光栅和蛇形误差扩散半色调】基于Floyd-Steinberg算法进行误差扩散半色调研究(Matlab代码实现)

&#x1f4a5;&#x1f4a5;&#x1f49e;&#x1f49e;欢迎来到本博客❤️❤️&#x1f4a5;&#x1f4a5; &#x1f3c6;博主优势&#xff1a;&#x1f31e;&#x1f31e;&#x1f31e;博客内容尽量做到思维缜密&#xff0c;逻辑清晰&#xff0c;为了方便读者。 ⛳️座右铭&a…...

JDspyder:京东自动化抢购解决方案的技术实现与实战指南

JDspyder&#xff1a;京东自动化抢购解决方案的技术实现与实战指南 【免费下载链接】JDspyder 京东预约&抢购脚本&#xff0c;可以自定义商品链接 项目地址: https://gitcode.com/gh_mirrors/jd/JDspyder 在电商秒杀和限量商品抢购的激烈竞争中&#xff0c;技术手段…...

MD源码#MDH5影视源码主题模版下载 苹果CMS V10版

内容目录一、详细介绍二、效果展示1.部分代码2.效果图展示三、学习资料下载一、详细介绍 MD源码#MDH5影视源码主题模版下载 苹果CMS V10版 一键部署版本&#xff0c;完美运营版本带采集规则模块 system/include.html–公共引用文件 system/header.html–头部文件 system/foo…...

Cursor AI代码助手:重塑IDE开发体验,从智能补全到项目级协作

1. 项目概述&#xff1a;当AI代码助手遇上IDE&#xff0c;Cursor如何重塑开发体验 如果你是一名开发者&#xff0c;最近一定在圈子里频繁听到“Cursor”这个名字。它不是一个全新的编程语言&#xff0c;也不是一个颠覆性的框架&#xff0c;但它却实实在在地在改变着许多人的编码…...

忘记加密压缩包密码?开源工具ArchivePasswordTestTool帮你轻松找回

忘记加密压缩包密码&#xff1f;开源工具ArchivePasswordTestTool帮你轻松找回 【免费下载链接】ArchivePasswordTestTool 利用7zip测试压缩包的功能 对加密压缩包进行自动化测试密码 项目地址: https://gitcode.com/gh_mirrors/ar/ArchivePasswordTestTool 你是否曾因忘…...