react-content-loader测试驱动开发:从测试到实现

【免费下载链接】react-content-loader ⚪ SVG-Powered component to easily create skeleton loadings. 【免费下载链接】react-content-loader 项目地址: https://gitcode.com/gh_mirrors/re/react-content-loader

你是否还在为组件开发中的边界情况头疼?是否经常在功能上线后才发现隐藏的bug?测试驱动开发(TDD, Test-Driven Development)或许能帮你解决这些问题。本文将以react-content-loader项目为例,带你完整走一遍从测试编写到组件实现的TDD流程,读完你将掌握:

  • 如何为React组件设计测试用例
  • 如何使用Jest和React Testing Library进行组件测试
  • 跨平台组件(Web/Native)的测试策略
  • 如何通过测试确保组件属性正确传递

项目概述

react-content-loader是一个基于SVG的React组件,用于轻松创建骨架屏加载效果。项目采用了跨平台设计,同时支持Web和React Native环境。

TDD开发流程

测试驱动开发遵循"红-绿-重构"(Red-Green-Refactor)的循环:

  1. :编写一个失败的测试
  2. 绿:编写足够的代码使测试通过
  3. 重构:优化代码结构而不改变功能

下面我们以ContentLoader组件为例,详细展示TDD流程。

测试用例设计

一个好的测试用例应该覆盖组件的主要功能点和边界情况。在react-content-loader项目中,测试用例主要分为以下几类:

1. 基础渲染测试

验证组件能否正确渲染基本结构。以Web端测试为例:

// [src/web/__tests__/ContentLoader.test.tsx](https://link.gitcode.com/i/d1743878e730073b7dc333f4e63d6fe5)
describe('when type is custom', () => {
  const customWrapper = renderer.create(
    <ContentLoader>
      <rect x="80" y="17" rx="4" ry="4" width="300" height="13" />
      <rect x="82" y="44" rx="3" ry="3" width="250" height="10" />
      <circle cx="35" cy="35" r="35" />
    </ContentLoader>
  ).root

  it('should render custom element', () => {
    const rect = customWrapper.findAllByType('rect')
    const circle = customWrapper.findAllByType('circle')

    expect(rect.length).toBe(3)
    expect(circle.length).toBe(1)
  })
})

2. 属性传递测试

确保组件的各种属性能够正确传递并生效。测试代码验证了从简单类型到复杂对象的各种属性:

// [src/native/__tests__/ContentLoader.test.tsx](https://link.gitcode.com/i/74965cbaf5f27d922ba99824571e5a86)
describe('Props are propagated', () => {
  const withPropsComponent = ShallowRenderer.createRenderer()
  withPropsComponent.render(
    <ContentLoader
      animate={false}
      height={200}
      preserveAspectRatio="xMaxYMax meet"
      backgroundColor="#000"
      rtl
      foregroundColor="#fff"
      speed={10}
      style={{ marginBottom: 10 }}
      width={200}
      beforeMask={<Rect />}
    >
      <Rect />
    </ContentLoader>
  )
  
  // 测试各种属性是否正确传递
  it("`speed` is a number and it's used", () => {
    expect(typeof propsFromFullField.speed).toBe('number')
    expect(propsFromFullField.speed).toBe(10)
  })
  
  // 更多属性测试...
})

3. 跨平台测试策略

项目同时支持Web和React Native平台,因此需要为不同平台编写相应的测试:

两者的测试结构相似,但针对不同平台的特性做了相应调整。例如,Web端直接使用SVG元素,而Native端使用react-native-svg库提供的组件:

// Web端测试查找原生SVG元素
const rect = customWrapper.findAllByType('rect')

// Native端测试查找react-native-svg组件
const rect = customWrapper.findAllByType(Rect)

组件实现

在编写了测试用例之后,我们来实现ContentLoader组件。根据TDD原则,我们只需要编写足够使测试通过的代码。

基础实现

ContentLoader组件的核心逻辑非常简洁:如果提供了子元素,则渲染自定义加载效果;否则使用默认的Facebook风格加载效果:

// [src/web/ContentLoader.tsx](https://link.gitcode.com/i/91c86120f03d7e66edfa3ca15832a638)
import * as React from 'react'
import { Facebook, IContentLoaderProps } from '.'
import Svg from './Svg'

const ContentLoader: React.FC<IContentLoaderProps> = props =>
  props.children ? <Svg {...props} /> : <Facebook {...props} />

export default ContentLoader

预设组件实现

项目提供了多种预设的加载效果,如Facebook风格、Instagram风格等。以Facebook风格为例:

// [src/web/presets/FacebookStyle.tsx](https://link.gitcode.com/i/b578048e718fd48bff99788a4b529c73)
import * as React from 'react'
import { IContentLoaderProps } from '..'
import ContentLoader from '../ContentLoader'

const ReactContentLoaderFacebook: React.FC<IContentLoaderProps> = props => (
  <ContentLoader viewBox="0 0 476 124" {...props}>
    <rect x="48" y="8" width="88" height="6" rx="3" />
    <rect x="48" y="26" width="52" height="6" rx="3" />
    <rect x="0" y="56" width="410" height="6" rx="3" />
    <rect x="0" y="72" width="380" height="6" rx="3" />
    <rect x="0" y="88" width="178" height="6" rx="3" />
    <circle cx="20" cy="20" r="20" />
  </ContentLoader>
)

export default ReactContentLoaderFacebook

测试执行与集成

项目的package.json中定义了完整的测试脚本,方便开发者执行测试:

// [package.json](https://link.gitcode.com/i/2433ac19eca1a8bbeb48f2b6289e12cc)
"scripts": {
  "test": "npm run test:tsc && npm run test:unit",
  "test:unit": "npm run test:unit:web && npm run test:unit:native",
  "test:unit:web": "jest -c jest.web.config.js",
  "test:unit:native": "jest -c jest.native.config.js",
  "test:watch": "npm run test:unit -- --watch",
  "test:tsc": "tsc"
}

执行以下命令可以运行所有测试:

npm test

或者分别运行Web和Native测试:

npm run test:unit:web
npm run test:unit:native

TDD带来的好处

通过react-content-loader项目的TDD实践,我们可以看到以下好处:

  1. 更可靠的代码:全面的测试覆盖确保了组件在各种情况下的行为符合预期
  2. 更好的API设计:在实现前先设计测试迫使开发者思考组件的API
  3. 自信的重构:有了测试保障,可以安全地进行代码重构
  4. 自动文档:测试用例本身就是组件使用方式的最佳文档

总结

本文通过react-content-loader项目展示了测试驱动开发的完整流程,从测试用例设计到组件实现,再到测试执行与集成。TDD虽然前期会增加一些工作量,但从长远来看,它能显著提高代码质量,减少bug,并使代码更易于维护和扩展。

项目的测试结构清晰,覆盖全面,为我们提供了一个很好的TDD实践范例。无论是Web端还是React Native端的组件,都可以借鉴这种测试思路,构建更健壮的应用。

如果你想深入了解项目的测试实现,可以查看完整的测试代码:

【免费下载链接】react-content-loader ⚪ SVG-Powered component to easily create skeleton loadings. 【免费下载链接】react-content-loader 项目地址: https://gitcode.com/gh_mirrors/re/react-content-loader

Logo

Agent 垂直技术社区,欢迎活跃、内容共建。

更多推荐