🦔

話題沸騰ポットに対して Property based testing を試してみる (2)給湯(水)させる

2020/10/26に公開

はじめに

話題沸騰ポットに対して Property based testing を試してみる (1)蓋の開け閉め、水を充填させるに引き続き
fast-checkを使ってProperty based testingを試しています。
題材として
テスト設計コンテストU-30クラスでテストベースに指定されている
「話題沸騰ポット要求仕様書 (GOMA‐1015型) 第7版にすることにしました.

準備

こちらに今回実装したコードを配置してみました。
Nodejsの環境が手元にあれば、試すことができます。

git clone https://github.com/freddiefujiwara/goma-1015.git
cd goma-1015
npm i
npm test

早速給湯に対してProperty based testingしてみましょう

給湯(水)させる

次に、ポットから中に入っている水を給水してみましょう
ボットに事前にコンセントに刺すplugInと外すplugOutとpour(給水ボタン)という機能をそれぞれ追加しておきましょう
要求仕様書には書いてないですが下記とします

  • 蓋が閉まっていないと、給水されない (*this is openの例外が発生)
  • コンセントに刺さってないと(Plug In)、給水されない (*plug should be connectedの例外が発生)
  • pourボタンを押下した秒数だけ給水される(10 ml/sec)
  • 空の状態でpourボタンを押すても水は給水されない 0ml給水される

これらをProperty based testingで確認していきましょう
fc.nat(10)を使って1-10秒までの任意の秒数のpourボタンを押下して確認していきます
また、fc.nat(1000)で空になったら0-1000までの任意のmlの水を充填しましょう

import fc from 'fast-check'
import Goma1015 from '../../src/lib/index'

describe('Goma1015', () => {
  .
  .
  .
  it('can pour', () => {
    let g = new Goma1015()
    //check definition
    expect(g.pour).toBeDefined()
    expect(g.plugIn).toBeDefined()
    expect(g.plugOff).toBeDefined()

    //deault plugOff
    expect(() => g.pour(15)).toThrowError(/plug should be connected/)
    //pouring needs to be pot closed
    g.open()
    g.plugIn()
    expect(() => g.pour(15)).toThrowError(/is open/)
    g.close()

    //plugOff
    g.plugOff()
    expect(() => g.pour(15)).toThrowError(/plug should be connected/)
    g.plugIn()

    //negative sec
    expect(() => g.pour(-1)).toThrowError(/can't be poured with negative sec/)
    //can not pour water anymore if empty
    expect(g.pour(100)).toBe(0)

    //property based testing for pour
    g = new Goma1015()
    //fill to full
    let water = 1000
    g.plugIn()
    g.open()
    g.fill(water)
    g.close()
    let sec = 0
    fc.assert(
      fc.property(fc.nat(10), fc.nat(1000), (s, w) => {
        //refill if empty
        //* water is poured 10 ml/sec
        if (sec >= water / 10) {
          expect(g.pour(s)).toBe(0)
          sec = 0
          water = w
          g.open()
          g.fill(water)
          g.close()
          return
        }
        //not empty
        //s equals 0 pour should be 0
        expect(g.pour(s) == 0).toBe(s == 0)
        sec += s
      }),
    )
  })
})

最後に

次はいよいよ沸騰させてみたいと思います
また、コードにもし間違いありましたらPull requestは大歓迎です。
長くなってしまいましたが 最後まで読んでいただきありがとうございました。

Discussion