前端测试完全指南:从单元测试到E2E测试

前端测试完全指南:从单元测试到E2E测试

大家好,我是蔓蔓。在大厂工作时,我们团队非常注重测试,这让我们的代码更加可靠。今天我来和大家分享前端测试的完整指南。

单元测试

Jest基础

javascript 复制代码
// sum.js
export function sum(a, b) {
  return a + b;
}

// sum.test.js
import { sum } from './sum';

test('adds 1 + 2 to equal 3', () => {
  expect(sum(1, 2)).toBe(3);
});

test('adds negative numbers', () => {
  expect(sum(-1, -2)).toBe(-3);
});

test('adds zero', () => {
  expect(sum(0, 0)).toBe(0);
});

Mock函数

javascript 复制代码
// fetchUser.js
export async function fetchUser(id) {
  const response = await fetch(`/api/users/${id}`);
  return response.json();
}

// fetchUser.test.js
import { fetchUser } from './fetchUser';

jest.mock('node-fetch');
import fetch from 'node-fetch';

test('fetchUser returns user data', async () => {
  const mockUser = { id: 1, name: '蔓蔓' };
  fetch.mockResolvedValue({
    json: () => Promise.resolve(mockUser)
  });

  const user = await fetchUser(1);
  expect(user).toEqual(mockUser);
  expect(fetch).toHaveBeenCalledWith('/api/users/1');
});

测试覆盖率

javascript 复制代码
// jest.config.js
module.exports = {
  coverageThreshold: {
    global: {
      branches: 80,
      functions: 80,
      lines: 80,
      statements: 80
    }
  },
  collectCoverageFrom: [
    'src/**/*.{js,jsx,ts,tsx}',
    '!src/**/*.test.{js,jsx,ts,tsx}'
  ]
};

集成测试

React组件测试

jsx 复制代码
// Button.jsx
function Button({ onClick, children }) {
  return (
    <button onClick={onClick} className="btn">
      {children}
    </button>
  );
}

// Button.test.jsx
import { render, screen, fireEvent } from '@testing-library/react';
import Button from './Button';

test('renders button with text', () => {
  render(<Button>Click me</Button>);
  expect(screen.getByText('Click me')).toBeInTheDocument();
});

test('calls onClick when clicked', () => {
  const handleClick = jest.fn();
  render(<Button onClick={handleClick}>Click me</Button>);
  
  fireEvent.click(screen.getByText('Click me'));
  expect(handleClick).toHaveBeenCalledTimes(1);
});

Vue组件测试

javascript 复制代码
// Button.vue
<template>
  <button @click="handleClick">{{ text }}</button>
</template>

<script>
export default {
  props: ['text'],
  methods: {
    handleClick() {
      this.$emit('click');
    }
  }
};
</script>

// Button.spec.js
import { mount } from '@vue/test-utils';
import Button from './Button.vue';

test('renders button', () => {
  const wrapper = mount(Button, {
    props: { text: 'Click me' }
  });
  
  expect(wrapper.text()).toBe('Click me');
});

test('emits click event', () => {
  const wrapper = mount(Button, {
    props: { text: 'Click me' }
  });
  
  wrapper.trigger('click');
  expect(wrapper.emitted('click')).toHaveLength(1);
});

E2E测试

Cypress基础

javascript 复制代码
// app.spec.js
describe('App', () => {
  beforeEach(() => {
    cy.visit('/');
  });

  it('displays welcome message', () => {
    cy.contains('Welcome');
  });

  it('logs in successfully', () => {
    cy.get('input[name="email"]').type('test@example.com');
    cy.get('input[name="password"]').type('password');
    cy.get('button[type="submit"]').click();
    
    cy.contains('Dashboard').should('be.visible');
  });

  it('shows error for invalid login', () => {
    cy.get('input[name="email"]').type('invalid@example.com');
    cy.get('input[name="password"]').type('wrong');
    cy.get('button[type="submit"]').click();
    
    cy.contains('Invalid credentials').should('be.visible');
  });
});

Playwright基础

javascript 复制代码
// app.spec.js
import { test, expect } from '@playwright/test';

test('has title', async ({ page }) => {
  await page.goto('/');
  await expect(page).toHaveTitle('My App');
});

test('login flow', async ({ page }) => {
  await page.goto('/login');
  
  await page.fill('input[name="email"]', 'test@example.com');
  await page.fill('input[name="password"]', 'password');
  await page.click('button[type="submit"]');
  
  await expect(page.locator('text=Dashboard')).toBeVisible();
});

测试策略

javascript 复制代码
const testStrategy = {
  unit: {
    coverage: 80,
    focus: 'individual functions and components'
  },
  integration: {
    focus: 'interactions between components'
  },
  e2e: {
    focus: 'end-to-end user flows',
    criticalPaths: ['login', 'checkout', 'search']
  }
};

总结

前端测试能提升代码质量和可靠性:

  1. 单元测试验证单个功能
  2. 集成测试验证组件交互
  3. E2E测试验证用户流程
  4. 合理设置测试覆盖率目标

技术应当有温度,可靠的测试能让用户使用更安心。

相关推荐
海兰1 分钟前
【水浒传:第二篇】AI江湖 —项目详细设计指南(一)
jvm·人工智能·游戏
AI客栈15 分钟前
Go Channel 事件分发:K8s 控制器升级零中断实践
人工智能
Bruce_Liuxiaowei22 分钟前
Prompt注入_我的AI编码助手被策反了
人工智能·ai·prompt·提示词·智能体
CryptoPP40 分钟前
快速对接东京证券交易所API数据:实战指南与代码示例
开发语言·人工智能·windows·python·信息可视化·区块链
米小虾1 小时前
AI Agent 上下文管理实战:让你的智能体不再"失忆"
人工智能·agent
凌云拓界1 小时前
文件管理:让AI安全操作你的电脑 ——CogitoAgent开发实战(三)
javascript·人工智能·架构·开源·node.js
火山引擎开发者社区1 小时前
Viking AI 搜索 CLI 正式发布:会说话,就能做搜索推荐
人工智能
云烟成雨TD1 小时前
Spring AI 1.x 系列【51】可观测性技术选型
java·人工智能·spring
unicrom_深圳市由你创科技1 小时前
基于Spring AI框架的RAG应用
人工智能·spring·机器学习