前端测试完全指南:从单元测试到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. 合理设置测试覆盖率目标

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

相关推荐
xsd202411181 小时前
3D双目相机 vs 面阵激光雷达:机器人的“眼睛“到底怎么选?
人工智能
2601_965619693 小时前
把开源项目Changelog自动做成更新视频,AI工作流
人工智能·开源·音视频
Json____3 小时前
PHP 突发严重安全漏洞,AI 开始改变网络安全的攻防方式
人工智能·web安全·php·it学习·wwwoop.com
fxss3 小时前
我用AI给娃写了个拼音闯关大冒险
人工智能
驭渊的小故事5 小时前
Spring AI Alibaba 实战:从maven依赖治理到声明式工具调用
java·人工智能·spring
北京中科新远科技5 小时前
高速光链路健康检查实战:DOM、FEC、误码与压力回归
人工智能·数据挖掘·回归
火山引擎和TA的超级拍档们5 小时前
超级拍档・光影新生|火山引擎 AIGC 主题峰会回顾
人工智能
冬奇Lab5 小时前
一天一个开源项目(第245篇):Raven —— ‘Harness 的 Harness‘,把 Claude Code、Codex 等智能体编排起来并让它递归自我改进
人工智能·开源·资讯