Cover Image for [TypeScript] Property based testing やってみる

[TypeScript] Property based testing やってみる

概要

Property-based testing という概念を最近やっと知ったので、Rustで試してみたのが → こちら 。TypeScriptでも試してみる。

TypeScript には fast-check いうライブラリがあるようなのでこれを導入して試してみる

導入方法

yarn add -D fast-check

テスト書いてみる

テスト対象

ちょうどブログ記事にシリーズごとにまとめられる機能を作った → こんな感じ

それ用のメタデータ追加を取得するコードを書いたのでテスト対象として使う

series.ts

import { createHash } from 'crypto'  
  
import { unique } from '../lib/arrays'  
import { getAllPosts } from './posts'  
  
type Series = {  
  hash: string  
  title: string  
}  
  
export const getSeries = (allPosts: { series?: string }[]): Series[] =>  
  unique(  
    allPosts  
      .flatMap(post => post.series)  
      .filter((series): series is string => series !== undefined)  
  ).map(title => {  
    const md5 = createHash('md5')  
    const hash = md5.update(title, 'binary').digest('hex')  
    return { hash, title }  
  })  
  
export const getAllSeries = (): Series[] => {  
  const allPosts = getAllPosts(['series'])  
  return getSeries(allPosts)  
}

テストコード

series.test.ts

import { createHash } from 'crypto'  
import fc from 'fast-check'  
import { describe, expect, test } from 'vitest'  
  
import { getSeries } from './series'  
  
describe('getSeries', () => {  
  test('md5 と title の組みが全て正しい', async () => {  
    const post = fc.record({  
      series: fc.option(fc.string(), { nil: undefined })  
    })  
  
    fc.assert(  
      fc.property(fc.array(post), posts => {  
        const actual = getSeries(posts)  
        actual.forEach(({ hash, title }) => {  
          const md5 = createHash('md5')  
          const expected = md5.update(title, 'binary').digest('hex')  
          expect(hash).toEqual(expected)  
        })  
      })  
    )  
  })  
})

所感

  • zodみたいな感じでテストデータの型を作れば、テストデータはFaker.js で作ったみたいなデータが挿入される
  • Faker.js で自分で作るよりは楽そう
  • テストが失敗したら最小限失敗するテストケースに縮退してくれるので、それを別のテストに切り出してデバッグするなどが便利
  • 雑多なデータを突っ込んでみて自分でも思ってなかったとこを通すみたいな使い方がいいのかも?
  • テストコード用のjsonとかをいちいち用意しておいて実装変わったからテストデータ用のjsonに大量の修正が必要になるとかは避けられそう。

参考