ゆふてっく。

ソフトウェアテスト界隈の話を書きます多分。

Jenkins の HTML Publisher Plugin を使って、Gauge が出したテスト結果の HTML レポートをいい感じに見れるようにする

Jenkins の Declarative Pipeline でやる方法です。
特に Gauge のレポート専用という訳ではなく、「Jenkins ジョブ実行中に作られた HTML ファイルを、Jenkins UI 上でいい感じに見れるようにする方法」です。

前提

環境

HTML レポートの構成

Gauge の HTML レポートはこんな感じの構成で出力されます。

reports
    └── html-report
        ├── css/
        ├── fonts/
        ├── images/
        ├── index.html
        ├── js/
        └── (test_project)/

手順

1. ビルド中に生成される HTML レポートを成果物として保存する

Pipeline の post セクションで、Gauge の出力する html-report ディレクトリをゴソッと保存します。
これにより、ジョブを何度実行してもビルド毎のレポート一式を保持し続けられるようになります。
(参考: https://www.jenkins.io/doc/pipeline/steps/core/)

pipeline {
  stages {
    stage('execute test') {
      steps {
        // テスト実行する
      }
      post {
        always {
          archiveArtifacts artifacts: 'reports/html-report/**/*', fingerprint: true
        }
      }
    }
  }
}

注意点

保存対象を reports/html-report/* とすると reports/html-report/index.html だけが保存されてしまいます。
reports/html-report/**/* とすると、ちゃんと html-report/ 配下をすべて保存してくれます。

2. HTML publisher で、保存した HTML レポートをジョブ画面に公開する

Pipeline の post セクションで、保存した HTML レポートを公開します。
これにより、Jenkins のジョブページのサイドメニューに HTML レポートへのリンクが出現します。
(参考: https://www.jenkins.io/doc/pipeline/steps/htmlpublisher/)

pipeline {
  stages {
    stage('execute test') {
      steps {
        // テスト実行する
      }
      post {
        always {
          archiveArtifacts artifacts: 'reports/html-report/**/*', fingerprint: true
          publishHTML target: [
            allowMissing: false,
            alwaysLinkToLastBuild: true,
            keepAll: false,
            reportDir: 'reports/html-report',
            reportFiles: 'index.html',
            reportName: 'HTML Report'
          ]
        }
      }
    }
  }
}

3. Jenkins のセキュリティ設定を変更する

この時点では、index.html を表示しても CSS などが何も読み込まれません。
Chrome の開発者ツールでコンソールを見ると以下のようなエラーが出ている状態です。

Blocked script execution in '<URL>' because the document's frame is sandboxed and the 'allow-scripts' permission is not set.

これは Jenkins のセキュリティ設定のためなので、正常に HTML レポートを読み込むためにはセキュリティ設定を下げる必要があります。
(参考: https://www.jenkins.io/doc/book/system-administration/security/configuring-content-security-policy/ )

手っ取り早くセキュリティ設定を変更する

Jenkins で Jenkins の管理 -> スクリプトコンソール を開き、以下のコマンドを実行します。

System.setProperty("hudson.model.DirectoryBrowserSupport.CSP", "")

コマンド実行後、即座に設定変更が反映され HTML レポートを正常に表示できるようになります。 (わたしの場合はブラウザキャッシュのクリアが必要でした。必ず必要かどうかは分かりません)

ただし、Jenkins の再起動などを行うと設定が元に戻ってしまうらしいです (まだ試してません)。

セキュリティ設定の変更を永続化する

Jenkins の起動時オプションで以下のように設定するらしいです (まだ試してません)。

java -Dhudson.model.DirectoryBrowserSupport.CSP="" -jar jenkins.war

備考

Jenkins 2.200 以降は、セキュリティ設定を変更するのではなく Resource Root URL というのを使っていい感じにできるっぽぃ?? のですが、会社の共用 Jenkins のバージョンは 2.164.3 なので 上記の方法を採りました。

組み合わせテストの落とし穴 〜有則と無則〜

ソフトウェアテスト初心者向けに、組み合わせテストの簡単な説明資料を作りました。
作ろうと思った動機はいまの職場の若者たちのためなのですが、内容は汎用的なのでせっかくだから公開します。

主な内容

大雑把な内容はこんな感じです。

  • 組み合わせテストには 有則無則 がある
    • 有則の説明&具体例
    • 無則の説明&具体例
  • 両者は異なる技法でテストケースを出す
  • 両者を混同するとマズいから注意!!!
    • 必要なテストケースが漏れる
    • 非現実的な量のテストケースができる

Google Apps Script で connpass から特定グループのイベント情報を定期取得して、更新があったら Slack に通知するようにした話

タイトルの通りです。
とくに難しいことや変わったことはしてないのですが、せっかくなので書き残しておきます。

目的

  • connpass でテスト系のイベントが公開されたら、早めに気付きたい
    (現状は「なんとなくTwitterで流れてきて知る」とかなんだけど、もっと適切に情報収集したい)
  • 「Slackに何かを自動通知」とか、世間では一般的だけど自分はやったことないのでやってみたい

使ったもの

やったこと

概要

  1. 予め、以下データをスプレッドシート上で定義しておく
    • 自分が興味ありそうなイベントを開催するグループの グループID の一覧
    • 前回取得時の最新イベントの 最終更新日時
  2. connpass APIを使い、上記グループ群のイベントを取得する (最終更新日時順)
  3. 取得したイベントの中に、「前回取得時より後に更新されたイベント」があったら以下を行う
    • Slack にイベント内容をPOSTする
    • スプレッドシートの「前回取得時の最新イベントの 最終更新日時」を更新する

具体的な内容

Google スプレッドシート

こんな感じのシートを作ります。
C列のグループIDを増やせば、検索対象のグループを増やせます。 (B列のグループ名は実際は使いませんが、人間が見て分かりやすくするために書いてます)

f:id:YUFU:20190503152544p:plain
スプレッドシートの内容

グループIDの調べ方

connpass のAPI仕様を見ると以下の記述があるのですが、

URLが https://connpass.com/series/1/ のグループの場合、グループIDは 1 になります。

現状(2019/05/03現在)だと、グループのTOPページのURIhttps://{グループ名?}.connpass.com/ になっています。
なので、「connpass APIに対し、グループ名か何かでイベント情報を検索 => レスポンスに含まれてるグループID を調べる」という とてもめんどくさい作業をしました。。

Google Apps Script

こんな感じです。
とりあえず動くので、まぁ今回の用途ではそれでいいかなーって思ってます。
(ていうか誰かがレビューしてくれる訳じゃないので、現状自力ではこれ以上直せない)

/////////////////////////////////////
// 定数
/////////////////////////////////////

// データ保存用のスプレッドシート
var SHEET = SpreadsheetApp.openById("★スプレッドシートのID★").getActiveSheet();

// 最新イベントの最終更新日時セル
var DATE_RANGE = SHEET.getRange(2, 1);

// connpassのイベント検索用URI
var CONNPASS_BASE_URI = "https://connpass.com/api/v1/event/";

// Slackの投稿用URI
var SLACK_URI = "https://hooks.slack.com/services/★省略★";


/////////////////////////////////////
// connpass関連
/////////////////////////////////////

// 検索対象のグループID群を取得する
function getGroupIds() {
  var groupIdRange = SHEET.getRange(2, 3, SHEET.getLastRow()-1);
  var groupIds = groupIdRange.getValues();

  return groupIds;
}

// 検索クエリを作る (グループIDで検索)
function createSearchQueryByGroupIds(groupIds, count) {
  return '?series_id=' + groupIds.join();
}

// 指定したグループのイベントを取得する
function getEvents(uri) {
  var response = JSON.parse(UrlFetchApp.fetch(uri).getContentText());

  return response.events;
}

// 新しく更新されたイベントを抽出する
function isUpdatedEvent(event) {
  var eventUpdatedTime = Date.parse(event.updated_at);
  var latestEventUpdatedTimeAtLastTime = Date.parse(DATE_RANGE.getValue());

  return eventUpdatedTime > latestEventUpdatedTimeAtLastTime;
}


/////////////////////////////////////
// Slack関連
/////////////////////////////////////

// Slack投稿用テキストを作成する
function createPostText(event) {
  var startDate = new Date(event.started_at);
  var startDateText = startDate.toLocaleString("ja-JP");

  var text =
      ":new: *" + event.title + "*" + "\n\n" +
        "- [Date] " + startDateText + "\n\n" +
          "- [Address] " + event.address + "\n\n" +
            "- [URI] " + event.event_url;

  return text;
}

// SlackにPOSTする
function postSlack(text) {
  var data = {
    "text": text
  };

  var options = {
    "method": "post",
    "contentType": "application/json",
    "payload": JSON.stringify(data)
  };

  UrlFetchApp.fetch(SLACK_URI, options);
}


/////////////////////////////////////
// スプレッドシート関連
/////////////////////////////////////

// 最新イベントの最終更新日時をスプレッドシートに保存する
// (次回の検索時、今回の最新イベントより新しいイベントのみを取得するため)
function saveLatestEventUpdatedDate(events) {
  var latestEvent = events[0];
  DATE_RANGE.setValue(latestEvent.updated_at);
}


/////////////////////////////////////
// main
/////////////////////////////////////

function notifyEvents() {
  var groupIds = getGroupIds();

  var searchQuery = createSearchQueryByGroupIds(groupIds);
  var searchUri = CONNPASS_BASE_URI + searchQuery;

  var updatedEvents = getEvents(searchUri).filter(isUpdatedEvent);

  if (updatedEvents.length > 0) {
    updatedEvents.forEach(function(event) {
      postSlack(createPostText(event));
    });

    saveLatestEventUpdatedDate(updatedEvents);
  }
  
  Logger.log(updatedEvents);
}
Slackの投稿用URIの調べ方

こちらのブログを参考にさせていただきました。 vaaaaaanquish.hatenablog.com

定期実行の設定

[G Suite Developer Hub][(https://script.google.com/home) で、作成したプロジェクトのメニューボタンからトリガーの設定するだけ。

f:id:YUFU:20190503153729p:plain
トリガー設定

ハマったところ

デバッグ実行中に undifined な変数にアクセスしちゃったときの動きが謎

undifined な変数にアクセスしちゃったとき、フツーに実行してればこんな感じで ReferenceError: 「{変数名}」が定義されていません。 ってエラーが出るのですが。

f:id:YUFU:20190503152701p:plain
実行時のエラー

デバッグ実行だと、エラーが出ずにそのまま進んでしまいます。

で、ループ処理とかしてると、こんな感じで画面下部の変数状態表示?が 何だか変になってきます (何故か arrayA[5][5][5] みたく階層化?してくけど、中身表示は [0, 1, 2, 3, 4] のまま)。

f:id:YUFU:20190503152743p:plain
デバッグ実行時

もしかしたらわたしに知識が無いから「何だか変」って思うだけで、実際は正しい動きなのかもしれませんが…とりあえず、基本的にデバッグ実行しながら進めてたので超ハマりました。。 (エディタの補完がないので、しょっちゅー変数名をTypoって あちこちで undifined になってた。。)

感想

わたしは普段、 IntelliJJava から Selenium 使って E2Eテストを書いたり、それを Jenkins で定期実行したりしてます。
それと比較すると、いろいろ勝手が違って印象的でした。

定期実行めちゃくちゃ簡単すごい

GASを選んだ理由(初めて使った)が「スクリプトの定期実行が簡単らしいから」なんですが、本当にスーパー簡単でビックリしました。
まさかのGUIから選択肢選ぶだけ。。しかもメンテフリー&無料。。(゚Д゚ )

Web/スプレッドシートとの親和性すごい

HTTPアクセスしたり、スプレッドシートの値を取得したり書き込んだりがめちゃくちゃ簡単でビックリしました。
UrlFetchApp.fetch(uri) の一行だけでレスポンス取ってこれるとか衝撃です。

動的型付け(?)ムズい

うっかり text型と number型を比較しちゃったりしても全然エラーが出ないので、細かいミスに気付きにくくて辛かったです。
また、関数宣言に戻り値の型が書かれてる状況に慣れてるせいか、パッと見で「こいつ何返すんだっけ? むしろ返さないんだっけ??」と混乱することが多かったです。
(とくに関数の分割方針や内容を試行錯誤してる最中など、関数側を戻り値なしに変更したのに、呼び出し側でそれに対応するのを忘れたり…)

変数や関数の名前の付け方が悪いのかもしれないですが、やっぱり明示的に書いてある方が把握しやすくていいなぁと思いました。

IDE(InteliiJ)すごい

今回Web上のGAS用エディタでスクリプト書いたのですが、いかに日々 IntelliJ に助けられてるか心底痛感しました。
間違ったこと書いたらその場で教えてくれるし、そもそも補完に出てこないから書く前に「自分がやろうとしてたこと間違ってた」って気付いたりするし。。

間違いは絶対に発生するので、「いかに早く間違いに気付かせてくれるか」ってめっちゃ大事なんだなーーーだからテスト自動化ってありがたいんだなーーーー…と しみじみ思いました (むりやり本業に繋げてくスタイル)。

おまけ・検討したけどダメだったアプローチ達

イベント開催告知ツイートを検索 => Slack に通知

最初、IFTTT の Use Twitter Advanced Search to post to Slack Channel という Applet を使って、「Twitter Advanced検索でイベント告知っぽぃツイートを見つけたら Slack に POST する」というアプローチを試しました。
ちなみに検索クエリは connpass.com テスト OR QA OR 品質 -申し込みました! です。

ただ、これだと「今日はこのイベントに参加します!」みたいなツイートも拾ってしまい、ノイズが多いのでやめました。

キーワードでイベント検索

connpass のイベントサーチAPIでは、「キーワード」を指定して検索することもできます。
が、この「キーワード」は「イベント名」だけでなく、「イベント説明」なども検索対象になっています。

そのため「QA」「テスト」「品質」などのキーワードで検索すると、イベント説明に「QAタイム (10分間)」「資格講座受講前の基礎力確認テスト」「高品質なアプリケーション開発」などが含まれたイベントがヒットしてしまい、これまたノイズが多すぎでダメでした。

ヒットしたイベント群の中から タイトルに「QA」「テスト」「品質」が含まれるものを抽出する…というアプローチも考えたんですが、タイトルにそれらの単語を含まないテスト系イベントも多かったため断念しました。

Windows10で 認証プロキシ環境下で GitHubに 443番ポートで SSH接続する方法

客先のネットワークポリシーが厳しくなって、認証プロキシを通さないとインターネット接続できなくなりました。
その環境下でGitHubSSH接続する方法が分からなくて調べたので、忘れないようにメモっておきます。

(なんでSSH接続したいかというと、HTTPS接続で試したけどGitHubの認証がうまくいかなかったせいです。
「ユーザ名とパスワードを2回ずつ訊かれて、正しいの入れてるのに認証失敗する」って感じでした。理由は調べてないので分かりません)

環境

  • Windows 10
  • Git for Windows 2.21.0
    • 操作は同梱の GitBush でやる
  • プロキシサーバの制約
    • Basic認証あり
    • 80/443以外のポートへのアクセスを許可しない

前提知識

GitHubSSHは443番ポートも使えるらしいです
(https://help.github.com/en/articles/using-ssh-over-the-https-port)

やったこと

.ssh/configの設定

.ssh/config をこんな感じにします。

Host github.com
    User git
    Hostname ssh.github.com
    Port 443
    IdentityFile ~/.ssh/id_rsa
    ProxyCommand connect.exe -H {PROXY_ADDRESS}:{PROXY_PORT} %h %p

ProxyCommand に設定してる connect.exe は、 C:\Program Files\Git\mingw64\bin にありました。
Git for Windows インストールすると勝手に入るみたいです。

環境変数の設定

ユーザ環境変数に以下を設定します。

変数名
HTTP_PROXY_USER {プロキシのユーザID}
HTTP_PROXY_PASSWORD {プロキシのパスワード}

動作確認

以下コマンドで、GitHubに接続してみます。

$ ssh -T github.com

こんな感じのメッセージが返ってきたら成功です

Hi {GITHUB_USER_NAME}! You've successfully authenticated, but GitHub does not provide shell access.

おまけ (検索にヒットさせる用)

環境変数にID/PWを設定しないでGitHubSSH接続を試みた場合、こういうエラーが出ました。
(なんで文字化けしてんのかは分かりません。。なんか日本語名のパスなんだろうけど。。)

$ ssh -T github.com
'C:\Program' ▒́A▒▒▒▒▒R▒}▒▒▒h▒܂▒▒͊O▒▒▒R▒}▒▒▒h▒A
▒▒▒▒\▒ȃv▒▒▒O▒▒▒▒▒܂▒▒̓o▒b▒` ▒t▒@▒C▒▒▒Ƃ▒▒ĔF▒▒▒▒▒▒Ă▒▒܂▒▒▒B
FATAL: Cannot decide password for proxy authentication.ssh_exchange_identification: Connection closed by remote host

原因結果グラフ(CEG)を語る夕べ 参加レポート

原因結果グラフ(CEG)を語る夕べ

先日「原因結果グラフ(CEG)を語る夕べ」という勉強会に参加しました。
内容がめちゃくちゃ面白くて感動し、「どこかにこの感動を書き残したい!」と思ったのでここに書きます(そのためにブログつくったw)。

なお、あくまで「わたしが話を聞いてこう理解した」のメモなので、実は間違いとかあるかもしれません(あったら教えてくれたら嬉しいです)。
また、内容も語られた時系列とは合ってません。

Data

内容

CEGTest の仕様について

生成されたデシジョンテーブルは、優先度の低いケースが除去されてる

優先度の低いケースって何?
  • AND条件時の、FF => F の組み合わせ
  • OR条件時の、TT => T の組み合わせ
具体例
AND条件のとき

#4 が除去される (A, B どっちの影響で 結果 = F になったか分からないため)。

#1 #2 #3 #4
A T T F F
B T F T F
結果 T F F F
OR条件のとき

#1 が除去される (A, B どっちの影響で 結果 = T になったか分からないため)。

#1 #2 #3 #4
A T T F F
B T F T F
結果 T T T F

中間ノードは、観測可能であることが前提

(2019/02/21追記:
CEGTest作者の Masaki Kase (@softest)さんから、「次のバージョンでは中間ノードが観測可能かどうかを変更できるように改善する予定です。」と教えていただきました!)

たとえば以下のような状況で、「都内在学の中学生」というパターンはデシジョンテーブルに現れない。

中間ノードありの原因結果グラフ

CEGTestのデシジョンテーブルは、あくまで 中間ノードが観測可能な前提 で作られている。 中間ノードが観測可能というのは、「 都内在住 または 都内在学 であれば、 都内在住学 である」ということが担保できるということ。

それが担保されている前提で、「 都内在住学である中学生である の関係」をテストしている。 なので、「結果ノード 割引される に至る条件が正しいかどうか」 の判定において、 「中間ノード 都内在住学 が T/F になっている理由」は考慮しない。 (中間ノードの話は、中間ノードで完結している)

「結果ノード 都内在住である , 都内在学である と、中間ノード 都内在住学である の関係」を見れば、必要な3パターンはすべて現れている (3パターン…OR条件なので、TF => T , FT => T , FF => F )。

中間ノードが観測できない場合は?

単体テストなど何らかの方法で、別途「中間ノードに至る条件が正しいかどうか」を担保する必要がある。 原因結果グラフの目的は、「すべての組み合わせパターン」をテストすることではない。

ちなみに、 OR条件は無則の組み合わせ、AND条件は有則の組み合わせ。 なので、OR条件であれば All-pair法などの組み合わせテスト技法を使うことができる (AND条件の場合は有則なので使えない)。

原因結果グラフの作り方 (考える順番)

  1. 結果を見つける
  2. その結果に至る条件を見つけて分解していく (結果 => 中間 => 原因 の順番で、右から左に書いてく)
  3. 頭の中で検証する
  4. ありえない組み合わせや制約を見つける

上記 1 〜 4 をグルグル繰り返して作ってく感じ。 一発で最適なものができなくてもヘコまなくて大丈夫。

ポイントとかコツとか

結果ノードの見つけ方
  • 仕様テキスト中に「〜の場合、●●する」って書いてある場合、往々にして「場合」の後が結果。 「場合」の前が原因たち。
中間ノードを作るか否かはどう判断する?
  • AND条件とOR条件が混在するときは必ず中間ノードを作る (じゃないと表現できないから)
  • 結果から考えて、仕様中にある言葉を中間ノードとして置いてく感じ (結果から考えるとやりやすい。 原因から考えると、「これは中間ノードにすべき? しないべき?」の判断が難しい)
原因ノードは完全同値分割で出すといい
完全同値分割って何?

例えば「6歳未満は●●する、65歳以上は▲▲する」という仕様のとき、 普通の(?)同値分割だと、条件ノードは 6歳未満 , 65歳以上 の2個。 完全同値分割だと、条件ノードは 6歳未満, 6-64歳, 65歳以上 の3個。

なんで完全同値分割がいいの?

上記の例を原因結果グラフにすると、以下のようになる。

普通の同値分割

6-64歳が現れない

完全同値分割

6-64歳が現れる

上記のデシジョンテーブルを見て分かるように、完全同値分割では現れる 6-64歳 というテスト条件(#3)が、普通の同値分割では現れない。 でもテストしたいので、条件ノードは完全同値分割にするとよい。 (「完全同値分割」って文言は、一般用語ではないが秋山さんは使ってる)

デシジョンテーブルと原因結果グラフの関係 (違い)

原因結果グラフは「デシジョンテーブルを作るための中間成果物」ではない。 両者の用途は違う。

デシジョンテーブル

  • 実装 (実際のソースコード) に近い
  • 内部の判定処理の順序を知らなければ書けない (デシジョンテーブルの条件欄は、内部処理の順番通りに書く必要がある)
  • 逆に、内部処理の判定順序を知ってるから- (Don't care)のセルが出現できる
    • - を使える条件は、以下すべてを満たす場合 (だったハズ…)
      • 対象の2ケース間で、結果が同じ
      • 対象の2ケース間で、1番下の条件以外がすべて同じ (1番下の条件のみが違う)
「デシジョンツリーからデシジョンテーブルを作る」と考えると分かりやすい

この↓ デシジョンツリーを、

デシジョンツリー

デシジョンテーブルで表現すると こう↓ なる。

#1 #2 #3 #4
A T F F F
B - T F F
C - - T F
結果 E1 E2 E3 E4
ポイント
  • A = true な時点で結果は E1 に確定するので、 #1 のケースでは B, C を判定する必要がない。 だから - になる。

原因結果グラフ

  • 実装ではなく、仕様と対応する

  • 内部の処理順序を知らなくても書ける

  • 内部の処理順序を考慮せず書くので、 - が出現しない (必ず T or F が入る)

  • 原因結果グラフから生成したデシジョンテーブルがこういう風になってても、 実際の処理順序は B => C => A でも全然いい

    #1 #2 #3 #4 #5 #6 #7 #8
    A T T T T F F F F
    B T T F F T T F F
    C T F T F T F T F
    結果 T T T T T T T F

違いのまとめ

  • デシジョンテーブルは実装に近い (実装と 1:1 にすることも可能)
  • 原因結果グラフは実装と関係なく、仕様の論理モデルを表現する
  • 自然言語で定義された仕様に対して、開発とテストが同じアプローチをすると同じ間違いをしやすい(バグを見逃しやすい)ので、「開発はデシジョンテーブル / テストは原因結果グラフ」という別々のアプローチでチェックするとよい

↓こんなイメージ?

開発はデシジョンテーブルで、テストは原因結果グラフでダブルチェックすると安心

デシジョンテーブルを使う上で注意すること

デシジョンテーブルの1ケースは、具体的テストケースではなく論理的テストケース。 なので実際は、デシジョンテーブルの1ケースに対して具体的テストケース複数件が作成されるのが普通。

たとえば、デシジョンテーブル上の条件が「メールに添付ファイルがある場合」だとしても、実際のテストでは以下のようなパターンをやりたくなるはず。

  • TEXTファイルを添付したり
  • EXEファイルを添付したり
  • 複数ファイルを添付したり…

原因結果グラフの用途について

原因結果グラフを、(テスト用途ではなく)仕様記述に使う事例とかあるのか?

  • 三菱(違うかも…うろ覚え)の国家系PJでの使用実績は聞いたことある
  • 松尾谷徹さん(CFD法提唱者)が仕様記述に使わせようとしたが、うまく行かなかった。開発者はシーケンシャルな思考には慣れてるが、論理モデルは何かうまく書けなかった (この話、ソフトウェアテスト技法ドリルに書いてあった)
    • 世代の問題かも。 「プログラミング教育 = フローチャート」みたいな世代だったせいでは。
    • 最近(オブジェクト指向とか論理プログラミングとか)の世代だったら意外とうまく書けるのかも知れないね〜

個人の感想

覚えたこと

原因結果グラフとデシジョンテーブルは違う

これが1番の衝撃。 「原因結果グラフはデシジョンテーブルを作るための中間成果物」と思い込んでた。 (先日この話を共有したところ他にもそう思ってるひとがいたので、結構多い誤解かもしれない)

デシジョンテーブルは内部の処理順序を知らなければ書けない」という言葉の意味がやっと理解できた

デシジョンツリー 〜 デシジョンテーブルの解説がとても分かりやすくて、目から鱗だった。 「処理順序を知らなければ書けない」というか、むしろ「内部の処理順序をそのまま表現したらこうなる」がデシジョンツリー&テーブルだったのかーーー!!!…的な。。

いままで「 A = true なら 結果 = E1 だから B, C- でいい」って言われても、ぶっちゃけ納得いってなかった。 (「でも実はバグがあって、 B, C の値が結果に影響を与えてたら? そのバグ見逃しちゃうんじゃないの?」って思ってた) でもそれはデシジョンテーブル(実装)的な発想じゃなくて、原因結果グラフ(仕様)的な発想だったんだなーと思った。

思ったこと

デシジョンテーブルは、ホワイトボックステストのための技法なんだなー

開発のひとに「こういう順番で処理してるよ」って言われても、開発のひとがそのつもりで実はミスしてるかもしれないから、そーゆー伝聞情報でデシジョンテーブルを作ってテストするのは危険だな〜…と思った。 (でも JSTQB の TA でデシジョンテーブルいっぱい出てくるから、違うのかもしれない。。)

少なくとも実務では、お話にもあった通り「開発はデシジョンテーブル、テストは原因結果グラフ」みたいな別ルートからの挟み撃ち? みたいなのが安心だなーと。

語る夕べめっちゃ面白い

色々議論とかもあって、すっっっっごい楽しかった。 テストについて真剣にあーだこーだ考えるのや話すのは楽しい。 ただ、めっちゃ少人数の会だったし皆さん仲良しっぽぃので、部外者のわたしは「何コイツ? 何で知らないヤツいんの??」みたいな空気読めない存在だったのかも知れない。 (やたら色々質問しちゃったし。。。。)

でもまたコッソリ行きたい。