🐧

「さくっ」とテストデータを作るための段取り

2022/06/15に公開

1. はじめに

この記事は、開発工程でテストデータを作らないといけない方向けの情報です。
コマンドを使って、さくっとテストデータを作ります。

  • 【利用者像】:

    • アプリケーション開発の局面で、とにかくテストデータが必要な方
    • 実務経験1年未満のエンジニア大多数。要員育成が必要なチームリーダーの方
  • 【利用シーン】:

    • テスト工程(ITa/ITb)
  • 【前提】:

    • 正常系・準正常系・異常系の違いがわかっている方が望ましい

2. 出来上がるもの

テスト実施のためのテストデータを作成します。
「たくさん」とは、~10万件レベル、「盛りだくさん」100万件以上とします。(盛りだくさんは、本記事では対象としていません)

対象データ:

  • CSV、TXT、SQL、JSON、XML
  • YAML、TOML

3. 作り方

3.1. データ作成計画を策定する

テスト仕様書をインプットに、テストの実施条件・期待値から、どういうテストデータが必要なのかを考えます。

計画の際の原則は以下。

  • 外部仕様書からテストデータのバリエーションを検討すること
  • 仕様書に書かれていないあいまいなことは開発者の課題とし、申し入れをすること(特に、データの相関性、準正常系・異常系の考慮もれが比較的多い)
  • テストデータはすべて準備してからテストに取り掛かること
  • テストデータは再利用を考慮すること

3.2. テストデータを作る

(1) 【基本編】数値データを作る(可変長・固定長)

$ seq 100
$ seq 10 100
$ seq -s " " -w 050
$ seq -s " " -w 010 100

(2) 【基本編】数値データを作る(乱数:重複あり)

1~10,000の乱数
$ for i in {0..10000}; do echo $(($RANDOM % 10000)) ; done

(3) 【基本編】数値データを作る(乱数:重複なし)

1~10,000の乱数(重複なし)
$ shuf -i 1-10000 -n 10000

(4) 【基本編】固定長の文字列データを作る

16桁100,000件(英字大文字小文字・数字) *重複の可能性あり
$ cat /dev/urandom | tr -dc 'a-zA-Z0-9' | fold -w 16 | head -10000  
:
VrRdKkEI6hVF5Cq9
16桁100,000件(英字大文字) *重複の可能性あり
$ cat /dev/urandom | tr -dc 'A-Z' | fold -w 16 | head -10000  
:
DGORYBFCPNJKSJEG

(5)【基本編】UUIDデータをたくさん作る

約50,000件 *重複なし
$ for i in `seq 50000`; do echo `uuidgen`; done | sort | uniq
:
3e25ab69-525a-469e-a8a0-1f16dc061b17

(6) 【基本編】複数カラムのデータをたくさん作る

hogehoge.awk *重複なし
BEGIN {
  maxNumber=100000;    # 10万件
  srand();
  printf("#seq, uid, point\n"); # CSVヘッダ
  for(i=1; i<=maxNumber; i++){
    printf("%d,u%08d,%d\n",   # CSVボディ
    i,
    i,
    substr(rand(), 3) );
  }
}
$ awk -f hogehoge.awk
#seq, uid, point
1,u00000001,973385
2,u00000002,295117
:
100000,u00100000,695035

(7)【基本編】エディタ機能でテストデータを編集する

CSVファイルなどの編集はエディタで微調整することが多いかと思います。
VisualStudioCode で使えるプラグインを紹介します。

■ VisualStudioCode: vscode-random(MIT licene)
https://github.com/jrebocho/vscode-random

■ VisualStudioCode: rainbow-csv(MIT licene)
https://marketplace.visualstudio.com/items?itemName=mechatroner.rainbow-csv

(8)【基本編】JSON データを大量につくる

いくつかツールはありますが、ここではDummy JSONを使って、テストデータを作成します。
まず、インプットファイルを作成し、次にDummy JSONを実行し、JSON ファイルを生成します。

sample-json.txt
[
    {{#repeat 5}}
    {
      "uid": {{@index}},
      "name": "{{firstName}} {{lastName}}",
      "email": "{{email}}"
    }
    {{/repeat}}
]
インプットファイルからJSONデータを生成
$ dummyjson sample-json.txt > test.json
$ cat test.json
------
[
    {
      "uid": 0,
      "name": "Liza Charley",
      "email": "liza.charley@unilogic.name"
    },
    {
      "uid": 1,
      "name": "Austin Tuck",
      "email": "austin.tuck@triosys.club"
    },
    {
      "uid": 2,
      "name": "Rolf Pettey",
      "email": "rolf.pettey@qualcore.org"
    },
    {
      "uid": 3,
      "name": "Alexa Raymond",
      "email": "alexa.raymond@acousticom.net"
    },
    {
      "uid": 4,
      "name": "Chloe Miers",
      "email": "chloe.miers@creatonix.biz"
    }
]

Dummy JSON(MIT License)
https://github.com/webroo/dummy-json

他にもWebサービスでも作成することが可能です。

Next JSON Generator
https://next.json-generator.com/

(9)【基本編】JSON データからCSVデータに変換する

jq を使って JSON から CSV に変換します。

csvヘッダなし
$ dummyjson sample-json.txt | jq -r '.[]|[.uid,.name,.email]|@csv'
------
0,"Shea Webster","shea.webster@fastfreight.xyz"
1,"Mitch Cumbie","mitch.cumbie@pancast.info"
2,"Lyle Sprowl","lyle.sprowl@quadtek.name"
3,"Yuri Seal","yuri.seal@dynaroc.org"
4,"Rufus Gamble","rufus.gamble@conixco.name"
csvヘッダあり 
$ dummyjson sample-json.txt | jq -r '["uid","name","email"],
(.[]|[.uid,.name,.email])|@csv'
------
"uid","name","email"
0,"Warren Gamble","warren.gamble@bellgate.net"
1,"Lyn Pendergast","lyn.pendergast@hassifix.name"
2,"Drew Furlough","drew.furlough@bellgate.org"
3,"Olivia Sager","olivia.sager@truext.gov"
4,"Alexa Jensen","alexa.jensen@solexis.me"
tsvヘッダなし
$ dummyjson sample-json.txt | jq -r ".[]|[.uid,.name,.email]|@tsv"
------
0       Jetta Pleiman   jetta.pleiman@westercom.me
1       Stephen Young   stephen.young@celmax.com
2       Gavin Magby     gavin.magby@celmax.org
3       Michael Leath   michael.leath@seelogic.net
4       Craig Zobel     craig.zobel@omnitouch.name

(10)【基本編】JSON データからXMLデータに変換する

json2xml を使って XML を生成します。

まず、事前に json2xml を組み込みます。

json2xmlの導入
$ pip3 install json2xml
$ pip3 list | grep json2xml
json2xml           3.20.0

今回は1~5件までランダムな件数のXMLファイルを作成します。3つのステップでXML ファイルに変換します。

  • a. JSONからXML変換用のpython ソースの準備
  • b. インプットファイルからJSON ファイルを生成
  • c. JSONファイルからXML ファイルに変換

a. JSONからXML変換用のpython ソースの準備

json2xml.py
from json2xml import json2xml
from json2xml.utils import readfromurl, readfromstring, readfromjson

data = readfromjson("test2.json")
print(json2xml.Json2xml(data).to_xml())

b. インプットファイルからJSON ファイルを生成

これまでと同じようにインプットファイル(sample2-json.txt)からJSONファイルを生成します。

インプットファイル(sample2-json.txt)
[
  {{#repeat min=1 max=5}}
    {
      "uid": {{add @index 1}},
      "name": "{{firstName}} {{lastName}}",
      "email": "{{email}}"
    }
    {{/repeat}}
]

c. JSONファイルからXML ファイルに変換

そのあとXMLファイルに変換します。

JSON データからXMLデータに変換
$ python3 json2xml.py
------
<?xml version="1.0" ?>
<all>
        <item type="dict">
                <uid type="int">1</uid>
                <name type="str">Marcus Pettey</name>
                <email type="str">marcus.pettey@keysoft.edu</email>
        </item>
        <item type="dict">
                <uid type="int">2</uid>
                <name type="str">Craig Jensen</name>
                <email type="str">craig.jensen@coolinga.net</email>
        </item>
        <item type="dict">
                <uid type="int">3</uid>
                <name type="str">Alexis Freeman</name>
                <email type="str">alexis.freeman@forecore.gov</email>
        </item>
</all>

(11)【基本編】JSON データからYAMLデータに変換する

json2yaml を使いましょう。

python-json2yaml (Apache License)
https://pypi.org/project/json2yaml/

JSON データからYAMLデータに変換
$ dummyjson sample2-json.txt | json2yaml
- uid: 1
  name: Lynetta Bourquin
  email: lynetta.bourquin@multilingua.org
- uid: 2
  name: Rosie Tindel
  email: rosie.tindel@opticast.info

【参考】: 他に変換用のツールとして、yjやXML, yaml, tomlを扱う参照用ツールとして jq(JSON用)xq(XML用), yq(YAML用), tomlq(TOML) があります。用途やケースによって、使い分けが必要ですが、ご参考までに紹介しておきます。

yj (Apache License)
https://github.com/sclevine/yj

python-yq, toml, xq (Apache License)
https://pypi.org/project/yq/

(12)【基本編】0バイトのデータを作る・0件のデータを作る

テストの時やシステム間連携時の本番環境の動作の初期動作時のお約束事として、初期データのファイルを作る場合があるかと思います。

0バイトのテストデータを作る
$ touch testfile.csv
0件のテストデータを作る
$ echo "#id,date, shopid, termid, itemname, price" > testfile.csv
$ echo "#eof" >> testfile.csv

(13)【基本編】「準正常系」「異常系」のテストデータを作る

CSVファイル デリミタの文字誤り(一か所)
$ sed s/,/:/ testfile_origin.csv >  testfile.csv
CSVファイル デリミタの文字誤り(一か所:3行目,5番目の,)
$ sed '3{; :a; s/,/:/5; t; N; ba;}' testfile_origin.csv >  testfile.csv
CSVファイル デリミタの文字誤り(すべて)
$ sed s/,/:/g testfile_origin.csv >  testfile.csv

(14)【基本編】1GiBのテキストデータを作る

1Gib
base64 /dev/urandom | head -c 1024M > testfile.csv

(15)【基本編】1GiBのバイナリデータを作る

0埋め
dd if=/dev/zero of=testfile.bin bs=1M count=1024
ランダム
dd if=/dev/urandom of=testfile.bin bs=1M count=1024

(16)【応用編】SQL構造にあわせて、テストデータを作る

3.3. テストデータをチェックする

(1)【基本編】重複データがないか検出する(テキストデータ)

cat double.txt
apple
apple
orange
$ uniq -c -d double.txt
2 apple                                 # 重複
$ echo $?                               # リターンは0     
0
$ cat uniq.txt
apple
orange
lemon
$ uniq -c -d uniq.txt                   # 重複データないと何も出力せず
$ echo $?                               # リターンは0     
0

(2) 【基本編】改行コードが正しいかチェックする(テキストデータ)

$ cat -e ファイル名
LF$      # LFのみの場合 $ ← Unix/Linux系はLFに統一しておく方がベター
CR^M           # CRのみの場合 ^M 
CRLF^M$        # CRLFのみの場合  ^M$
-----------------------------------
以下は改行データを作成する場合の実行例
$ echo -en  "LF\xA" > testdata.csv
$ echo -en  "CR\xD" >> testdata.csv
$ echo -en  "CRLF\xD\xA" >> testdata.csv
$ od -tx1c testdata.csv
0000000  4c  46  0a  43  52  0d  43  52  4c  46  0d  0a
          L   F  \n   C   R  \r   C   R   L   F  \r  \n	  

(3) 【基本編】文字コードをチェックする(テキストデータ)

$ file ファイル名
JIS.txt:       ASCII text, with escape sequences
ShiftJIS.txt:  Non-ISO extended-ASCII text, with CRLF line terminators
UTF8BOM.txt:   UTF-8 Unicode (with BOM) text, with CRLF line terminators
UTF8noBOM.txt: UTF-8 Unicode text, with CRLF line terminators

$ nkf --guess *txt
JIS.txt: ISO-2022-JP (LF)
ShiftJIS.txt: Shift_JIS (CRLF)
UTF8BOM.txt: UTF-8 (BOM) (CRLF)
UTF8noBOM.txt: UTF-8 (CRLF)
  • Windows 環境でテストデータを作っているとBOMつきで保存してしまい、Linux上でバイナリーデータとして扱われる場合があります。ファイルに保存するとき、注意しましょう。
  • 文字コードあたりと改行コードもあわせて、チェックしておきましょう。
  • nkf(ネットワーク漢字フィルター) は、通常のクラウドサービスの標準設定では導入されていません。現場で助かるケースがあるので、apt-get install nkf で導入しましょう。

(4) 【基本編】テストデータを比較する(テキストデータ)

$ diff --rc ファイル名1 ファイル名2
diff -rc testdata1.csv testfile2.csv
*** testdata1.csv        2022-06-15 04:44:51.054067000 +0000
--- testfile2.csv        2022-06-15 04:45:53.320013800 +0000
***************
*** 1,6 ****
  1,2,3,4,5,6
  1,2,3,4,5,6
! 1,2,3,4,5,6       ←どの行が違うか(ファイル名1)
  1,2,3,4,5,6
  1,2,3,4,5,6
  1,2,3,4,5,6
--- 1,6 ----
  1,2,3,4,5,6
  1,2,3,4,5,6
! 1,2,3,4,5:6       ←どの行が違うか(ファイル名2)
  1,2,3,4,5,6
  1,2,3,4,5,6
  1,2,3,4,5,6

$ cmp -b testdata1.csv testfile2.csv
testdata1.csv testfile2.csv differ: byte 34, line 3 is  54 ,  72 :
  # 1バイト単位にどこの位置の何が違うかを表示

(5) 【基本編】テストデータを比較する(画像データ)

ImageMagick のcompare コマンドを使って、想定どおりのテストデータが出来ているかを
確認します。

$ compare 入力ファイル名1 入力ファイル名2 出力ファイル(比較結果))
$ compare sample.jpg sample.png sample-diff.png

少しでも違いのある箇所は赤く示されています。

【sample-diff.png】

3.4. テスト時のオペレーションを記録する

複数人開発で同時にデータベースを触りながら、テストデータを作るようになると、開発の現場で問題になる場合があります。日ごろからオペレーションの際の記録はとっておくようにしましょう。

(1)【基本編】テスト時のオペレーションログを残す(コマンド実行の場合)

操作例
$ script -a dataimport-op`date +"%Y%m%d"`.log
# 操作を行う (例 : ls -al /usr/local/src)
#
exit   # スクリプトを抜ける
Script done, file is dataimport-op20220615.log

(1)【基本編】テスト時のスナップショットを残す(GUI・WUI操作の場合)

(2)【基本編】データベースの内容・ログファイルを出力する

個人で実施している場合は特に意識しないかもしれませんが、複数人で開発する場合は、
データベースの更新内容やログファイルを必ず残しましょう。

  • テスト実施前: 実施条件
  • テスト実施後: 何が更新されたか、何を出力されているか

(3)【基本編】ミリ秒単位で記録をとる

後工程になればなるほど、性能問題が発生したときの対処が難しくなります。
はやい工程の段階から、記録を残して処理時間やレスポンス時間を求めるようにしましょう。

以下は シェルの場合です。

ナノ秒、マイクロ秒、ミリ秒
$ export TZ=JST-9         # タイムゾーンによる出力補正
$ date +"%Y/%m/%d %T.%N"
2022/06/15 00:18:21.454898075
$ date +"%Y/%m/%d %T.%6N"
2022/06/15 00:18:40.574924
$ date +"%Y/%m/%d %T.%3N"
2022/06/15 00:19:13.522

(4)【基本編】テストデータを整理し、報告する

作ったテストデータは、プロジェクトのフォルダに配置します。
決して、テストデータやエビデンスは、個人持ちしないようにしましょう。

期日通りにできていない(できそうにない)場合は、速やかに報告しましょう。

(5)【基本編】テストエビデンスを整理し、報告する

テストデータ作成後、テストデータ作成者が、そのままテスト実施者になることもあります。
テスト項目を消化する際には、エビデンスを記録し、報告しましょう。

  • 条件
    • 環境条件
    • 初期設定条件
  • テストデータ
     - テスト項目に沿ったテストデータ
     - (必要に応じて)テスト仕様書へもフィードバック
  • エビデンス
    • 画面のスクリーンショット
    • コマンドオペレーション
    • 帳票
    • レシート
    • 出力ファイル
    • 出力メール
    • ログファイル(業務・監査・システム)
    • データベースの更新結果
    • パフォーマンスログ
  • 報告内容
    • テスト進捗(デイリー)
    • テスト仕様書の結果
    • インシデント
    • 問い合わせ内容

4. まとめ

最近はインターネットサービス上にテストデータ作成サービスがあり、「なんで回りくどい」と感じた方もいるかと思います。便利なものがない、個人利用では使えるものが使えない最低限のマシン環境下で、業務をこなすことを想定し、シンプルなLinuxベースで実現できれば、と思い、記事を書いてみました。WSL2 が出たおかげで、本当のWindowsと本当のLinuxを、ストレスなく使いこなせるようになってきましたね。今後は android, ipad, Macとの融合に期待。

あまりまとまっていませんが、本日はここまで、とします。

5. 参考

この記事は、以下の曲を聴きながら、作成しました。

  1. get back(the beatles)
  2. telegram sam(t.rex)
  3. satisfaction(the rolling stones)
  4. my sharona(the knack)
  5. synchronicity I(the police)
  6. smoke on the water(deep purple)
  7. back in black(ac/dc)
  8. purple haze(jimi hendrix)
  9. rock and roll(led zepperin)
  10. sailing(rod stewart)

ここまで読んでいただいた方、ありがとうございます。
では、また

Discussion