LoginSignup
5

More than 5 years have passed since last update.

Tcl/Tkで作ったGUIアプリの単体テストの方法

Posted at

Tcl/Tkで作ったGUIアプリは単体テストしにくいですよね。特に画面の状態遷移があるような本格的なアプリケーションだと、必要な機能を呼び出すまでにいくつかの手順が必要になって泣きそうになります。

よく考えればGUIを組み立てなくても必要なオブジェクトさえあればテストできるので、フレームを表示させないでテストしてみたら効率が上がったので紹介します。

やり方

  1. テスト対象のオブジェクト(buttonやlabel)に必要なフレームのみを生成する。packやgridはしない。
  2. テスト対象のオブジェクトを生成する。同じくpackやgridはしない。
  3. テストを実行する
  4. テスト用に作ったオブジェクトを destroy する。

サンプルソース

utest.tcl
#---------------------------------------------------------------------
# GUIアプリケーションのソース
proc gui { } {
    # フレームの定義
    frame .f
    frame .f.foo
    frame .f.baa
    frame .f.huga
    frame .f.huga.hum

    pack .f
    pack .f.foo .f.baa .f.huga .f.huga.hum

    # ボタンの定義
    button .f.foo.b -text "foo"
    pack .f.foo.b 
    button .f.baa.b -text "baa"
    pack .f.baa.b
    button .f.huga.hum.b -text "huga.hum"
    pack .f.huga.hum.b
}

# 全てのボタンのパスを取得
proc get_all_buttons { } {
    return ".f.foo.b .f.baa.b .f.huga.hum.b"
}

# テストされる手続き
# get_all_buttons が返すボタンを全て無効にする
proc disalbe_all_buttons { } {
    foreach b [get_all_buttons] {
    $b configure -state disable
    }
}

#----------------------------------------------------------------------
# テスト用のソース
# disalbe_all_buttonsのテスト
# 
set err 0
set log ""
proc test_disable_all_buttons { } { 
    global err log

    # ダミーで、ボタンとボタンに必要なフレームを作る
    foreach f {.f .f.foo .f.baa .f.huga .f.huga.hum} { 
        frame $f
    }

    # テスト用にボタンを作る。
    foreach b [get_all_buttons] {
        button $b -state normal
    }

    # テストされる手続きの呼び出し
    disalbe_all_buttons

    # 結果のチェック
    foreach b [get_all_buttons] {
        set state [$b cget -state]
        if { $state != "disabled" } {
            append log "Error $b is not disabled ($state)\n"
            incr err 1
        } else {
            append log "PASS $b\n"
        }
    }

    # 一番上のフレームを削除して、ボタンとフレームを全て削除する。
    destroy .f
}

# テストの実行
test_disable_all_buttons

# 結果の表示(通常はファイルに出す)
if { $err == 0} {
    tk_messageBox -type ok -title "test終了"  -message  "$log"
    exit 0
} else {
    tk_messageBox -type ok -title "test終了(エラー)"  -message  "$log" -icon error
    exit 1
}

これで、wish utest.tcl で単体テストが実行出来ます。このやり方で小分けにしてテストしたところ、今まで動いていたアプリも細かいバグをいくつか見つけました。もう一つwishとプロセス間通信をしながらテストするバッドノウハウがいくつかあるのですが、それはまた別の機会に。

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
5