lint-test✅
eslint 是如何工作的?
答案
- 加载配置 通过 loadConfigFile 加载配置, 配置规则详见 config file
- 解析 AST 默认采用 espree. AST 规则遵循 ESTree, ESLint 也支持 markdown/css 等解析,参考 markdown 解析, 可以通过 eslint explorer 查看不同 AST
- Rule 遍历节点按规则检查,每条规则接收上下文(RuleContext),在特定 AST 节点上报告问题并可返回 fixer(基于 SourceCode)生成补丁
- 生成报告
- 格式化 按规则提供 fixer 自动修复
eslint 如何实现增量 lint?
答案
-
结合 git diff 与 eslint,只对 MR/PR/commit 变更文件 lint
# 方案1:命令行增量 lint(仅校验 master 分支与当前分支变更的 js 文件)
git diff --name-only --diff-filter=d master | grep '\.js$' | xargs eslint -
lint-staged + husky(pre-commit 钩子自动 lint 暂存文件)
npm install lint-staged husky --save-dev
{
"husky": {
"hooks": {
"pre-commit": "lint-staged"
}
},
"lint-staged": {
"*.js": ["eslint --fix", "git add"]
}
}
延伸阅读
- lint-staged — 暂存文件 lint 工具
- husky — git 钩子管理工具
- ESLint CLI — 命令行用法
- Git diff-filter — 文件过滤参数说明
TDD、BDD、DDD 分别指?
答案
核心概念:
- TDD(测试驱动开发):先写测试再写实现,强调“红-绿-重构”循环。
- BDD(行为驱动开发):关注行为描述,测试用例更贴近业务与非技术沟通。
- DDD(领域驱动设计):以业务领域为核心的软件设计方法论,强调领域建模与分层架构。
示例说明:
// TDD 示例
test('加法函数', () => {
expect(add(1, 2)).toBe(3)
})
// 先写测试,再实现 add
function add (a, b) { return a + b }
提示
BDD 测试用例通常采用 Given-When-Then 语法,便于业务沟通。
面试官视角:
- 要点:能区分三者本质、适用场景、优缺点
- 加分项:能举出实际项目应用、理解 TDD/BDD/DDD 组合价值
- 常见失误:混淆 DDD 与测试方法、只会背定义
延伸阅读
测试金字塔与主流测试类型有哪些?
答案
核心概念:
- 测试金字塔分为:单元测试(底层)、集成测试(中层)、端到端测试(顶层),越往上越重但数量应减少。
- 组件测试、静态分析也是前端常见测试手段。
- 工具:Jest、Mocha、Cypress、React Testing Library、ESLint 等。
示例说明:
// 单元测试示例
function add(a, b) { return a + b }
test('add', () => {
expect(add(2, 3)).toBe(5)
expect(add(-1, 1)).toBe(0)
})
// 端到端测试示例(Cypress)
it('添加商品并结算', () => {
cy.visit('https://your-ecommerce-site.com')
cy.get('.product-item').first().click()
cy.get('.add-to-cart-button').click()
cy.get('.cart-icon').click()
cy.get('.checkout-button').click()
})
})
面试官视角:
- 要点:能描述金字塔结构、各层测试目标、主流工具
- 加分项:能结合实际项目说明测试策略
- 常见失误:只会单一测试类型、不理解金字塔分层意义
延伸阅读
单元测试和端到端测试的区别?
答案
类型 | 测试范围 | 依赖 | 速度 | 维护成本 | 典型工具 |
---|---|---|---|---|---|
单元测试 | 单个函数/类/模块 | 低,常用 mock | 快 | 低 | Jest, Mocha |
端到端测试 | 整个系统/用户流程 | 高,需完整环境 | 慢 | 高 | Cypress, Puppeteer |
示例说明:
// 单元测试
function add (a, b) { return a + b }
test('add', () => {
expect(add(1, 2)).toBe(3)
})
// 端到端测试
describe('登录流程', () => {
it('用户登录', () => {
cy.visit('/login')
cy.get('input[name=username]').type('user')
cy.get('input[name=password]').type('pass')
cy.get('button[type=submit]').click()
cy.contains('欢迎').should('exist')
})
})
面试官视角:
- 要点:能清晰区分测试范围、依赖、速度
- 加分项:能结合实际项目说明两者配合
- 常见失误:混淆测试目标、只会单一类型
延伸阅读
如何针对 React Hooks 写单测?
答案
核心概念:
- 针对自定义 Hook 推荐用
@testing-library/react-hooks
,可隔离测试 Hook 逻辑。 - 若依赖 Context,可用 wrapper 包裹。
- 需用
act
保证状态同步。
示例说明:
// useCounter.js
import { useState, useCallback } from 'react'
export default function useCounter(initialValue = 0) {
const [count, setCount] = useState(initialValue)
const increment = useCallback(() => setCount(c => c + 1), [])
const decrement = useCallback(() => setCount(c => c - 1), [])
return { count, increment, decrement }
}
// useCounter.test.js
import { renderHook, act } from '@testing-library/react-hooks'
import useCounter from './useCounter'
describe('useCounter', () => {
it('默认值', () => {
const { result } = renderHook(() => useCounter())
expect(result.current.count).toBe(0)
})
it('递增', () => {
const { result } = renderHook(() => useCounter())
act(() => { result.current.increment() })
expect(result.current.count).toBe(1)
})
it('递减', () => {
const { result } = renderHook(() => useCounter(10))
act(() => { result.current.decrement() })
expect(result.current.count).toBe(9)
})
})
面试官视角:
- 要点:能独立测试 Hook、理解 act 用法
- 加分项:能处理复杂依赖(如 Context)
- 常见失误:直接在组件中测 Hook、未用 act
延伸阅读
代码覆盖率一般有什么手段?
答案
核心概念:
- 覆盖率衡量测试执行代码比例,常见指标:语句、分支、函数、行覆盖率。
- 工具:Jest(内置)、nyc/Istanbul、Cypress、Chrome DevTools Coverage。
- CI 可用 Codecov/Coveralls 自动统计。
示例说明:
// Jest 生成覆盖率报告
jest --coverage
提示
Chrome DevTools Coverage Tab 可手动分析页面覆盖率,适合前端调试。
面试官视角:
- 要点:能说出覆盖率指标、主流工具
- 加分项:能结合 CI/CD 自动化
- 常见失误:只会跑测试,不关注覆盖率
延伸阅读