ほんじゃらねっと

ダイエット中プログラマのブログ

プログラムテスト用の組み合わせパターンデータをササッと作るためのテンプレ【Python/Clojure】

f:id:piro_suke:20160729002821j:plain

他の誰かが作成した検索プログラムやストアドファンクションを

修正させられる時に、

検索対象のテストデータとか

プログラムに渡す検索パラメータのテスト用データを

必要なパターン分作成してテストするのだけど、

抜け漏れのないテストデータを簡単に生成できないものかと調べていたら、

PythonにもClojureにも組み合わせリストを作成してくれるライブラリがあった。

組み合わせデータを作成する

必要なパターンの組み合わせデータを自前で作成するのはなかなかめんどくさい。

例えば商品検索機能のテストデータを作成する際、

「商品データ」が

属性として「有効区分(0:無効、1:有効)」と「表示区分(0:非表示、1:表示)」を

持っていて、「有効」で「表示」の商品のみ検索結果に含まれる、

ということを確認したい場合に

テストデータとしては「有効区分」2パターンと「表示区分」2パターンの

組み合わせで下記の4パターンの組み合わせデータが欲しい:

(0:無効, 0:非表示)
(0:無効, 1:表示)
(1:有効, 0:非表示)
(1:有効, 1:表示)

これにさらに「商品カテゴリ」3パターンのどれでも正常に動作することを

確認したいので、2x2x3=12パターンの組み合わせデータを作成する、

みたいなことを簡単にしたい。

調べてみるとプログラミング言語によっては順列や組み合わせを扱う

ライブラリが用意されており、

これを使うと簡単に組み合わせデータを作成できそう。

例えばPythonなら標準モジュールに含まれる

itertoolsのproduct関数を使用することで

組み合わせデータを作成することができる。

10.1. itertools — 効率的なループ実行のためのイテレータ生成関数 — Python 3.6.1 ドキュメント

qiita.com

Clojureの場合は、clojure.math.combinatoricsというパッケージに

「cartesian-product」という関数があり、これが使えそうだ。

github.com

Clojure版組み合わせテストデータ作成スクリプト

今回はClojureのcartesian-product関数を使って

データベースにテスト用商品データを生成する

サンプルスクリプトを作ってみた。

project.clj

(defproject test-data-creator "0.1.0-SNAPSHOT"
  :description "FIXME: write description"
  :url "http://example.com/FIXME"
  :license {:name "Eclipse Public License"
            :url "http://www.eclipse.org/legal/epl-v10.html"}
  :dependencies [[org.clojure/clojure "1.8.0"]
                 [org.clojure/math.combinatorics "0.1.3"]
                 [korma "0.4.2"]
                 [org.clojure/java.jdbc "0.4.2"]
                 [org.postgresql/postgresql "9.4-1203-jdbc42"]]
  :main ^:skip-aot test-data-creator.core
  :target-path "target/%s"
  :profiles {:uberjar {:aot :all}})

core.clj

(ns test-data-creator.core
  (:gen-class)
  (:require [korma.db])
  (:require [korma.core :as kc])
  (:require [clojure.math.combinatorics :as combo]))

;; database defs
(korma.db/defdb db
                {:user "<DBユーザー名>"
                 :password "<DBパスワード>"
                 :subname "//localhost:5432/<DB名>"
                 :subprotocol "postgresql"})
(kc/defentity items)

(defn- insert-items
  []
  (let [product (combo/cartesian-product
                  [0 1] ; 0:有効区分
                  [0 1] ; 1:表示区分
                  ["カテゴリ1" "カテゴリ2" "カテゴリ3"] ; 2:商品カテゴリ
                  )]
    (doseq [[i p] (map-indexed vector product)
            :let [id (+ i 1)]]
      (kc/insert items
                 (kc/values
                   {:item_id id ; 商品コード
                    :item_name (str "テスト商品" id) ; 商品名
                    :item_category (nth p 2) ; 商品カテゴリ
                    :is_enabled (nth p 0) ; 有効区分
                    :is_visible (nth p 1) ; 表示区分
                 )})))))

(defn -main
  [& args]
  (insert-items))

有効区分、表示区分、商品カテゴリの組み合わせデータを

生成し、作成したデータをすべてitemsテーブルにinsertしてる。

insert-items関数のcombo/cartesian-productの引数に

渡したパターン分の組み合わせデータが生成されるので、

組み合わせの要素を増やしたい時は引数にパターンリストを追加する。

それをinsert文で該当する項目にセットすれば

簡単に組み合わせデータが入ったテーブルが出来上がる。

便利だ。

おわり

最近、作成したスクリプトが仕事で役に立つ機会が増えてきて嬉しい。

ソフトウェアテスト293の鉄則

ソフトウェアテスト293の鉄則