コンテンツにスキップ

Goのテストツール@アプリのホワイトボックステスト

はじめに

本サイトにつきまして、以下をご認識のほど宜しくお願いいたします。


01. ホワイトボックステストのツール

整形

  • 標準のgo fmtコマンド


静的解析

▼ ベストプラクティス

  • 標準のgo vetコマンド

▼ 脆弱性

  • govulncheck
  • gosec


単体テスト、機能テストツール

  • 標準のgo fmtコマンド


02. 標準のテストツール

標準のテストツールとは

goコマンドが提供するホワイトボックス機能のこと。


網羅率

網羅率はパッケージを単位として解析される。


03. 設計規約

パッケージ名

▼ ホワイトボックステスト

テストファイルのパッケージ名が、同じディレクトリ配下にある実際の処理ファイルのパッケージ名と同じ場合、それはホワイトボックステストになる。

▼ ブラックボックス風のホワイトテスト

テストファイルのパッケージ名が、同じディレクトリ配下にある実際の処理ファイルに『_test』を加えたパッケージ名の場合、それはブラックボックステスト風のホワイトテストになる。

補足として、Goでは1つのディレクトリ内に1つのパッケージ名しか宣言できないが、ブラックボックステストのために『_test』を加えることは許されている。


インターフェースの導入

テストできない構造体はモックに差し替えられることなる。

この時、あらかじめ実際の構造体をインターフェースの実装にしておく。

テスト時に、モックもインターフェイスの実装とすれば、モックが実際の構造体と同じデータ型として認識されるようになる。

これにより、モックに差し替えられるようになる。


テーブル駆動テスト

テストデータ (datain) と期待値 (expectedwant) をファイル (例:.json.yaml) として用意しておく。

これをReadFile関数で読み出し、テストケースの構造体を定義する。

テストケースの構造体を反復処理し、テストを実施する。

package test

import (
    "io/ioutil"
    "testing"
)

/**
 * foo関数をテストする
 */
func TestFoo(t *testing.T) {

    // ファイルを読み込む。
    expected_foo_succeed_status, _ := ioutil.ReadFile("../testdata/expected/foo_succeed_status.json")
    data_foo_succeed_status, _ := ioutil.ReadFile("../testdata/data/foo_succeed_status.json")

    expected_foo_failed_status, _ := ioutil.ReadFile("../testdata/expected/foo_succeed_status.json")
    data_foo_failed_status, _ := ioutil.ReadFile("../testdata/data/foo_succeed_status.json")

    // テストケース
    cases := []struct {
        // テストケース名
        name string
        // 期待値
        expected string
        // テストデータ
        data []byte
    }{
        {
            name:     "TestFoo_SucceedStatus_ReturnOk",
            expected: expected_foo_succeed_status,
            data:     data_foo_succeed_status,
        },
        {
            name:     "TestFoo_FailedStatus_ReturnOk",
            expected: expected_foo_failed_status,
            data:     data_foo_failed_status,
        },
    }

    // テストケースを反復で処理する。
    for _, tt := range cases {
        t.Run(tt.name, func(t *testing.T) {

            // foo関数を実行し、実際値を作成する。

            // 期待値と実際値を比較する。
            assert.JSONEq(t, tt.expected, actual)
        })
    }
}