ScenarioTest=Visual Studio専用のテスト自動化ツール

ScenarioTestとは何か?

エモーションソフトが提供するScenarioTestは、Webアプリケーションの自動テストを作成するためのVisual Studioのプラグインです。テスト自動化プログラムを自作するユーザー向けに、最小限のコードの記述でテスト自動化プログラムの作成に必要な様々な機能を埋め込むことを可能にします。

Software test to find bugs in the programming code
Webアプリケーションのテスト自動化を行うVisual Studioの拡張機能の紹介です。

単にテスト自動化のための拡張機能ライブラリとしてだけではなく、アプリケーションの単体機能の開発段階でテスト自動化プログラムを書き始めるという新しい開発スタイルを実現するポテンシャルを持っています。この点でScenarioTestは他のテストツールと比べて非常にユニークな製品となっています。それでは実際にScenarioTestを使うと何が出来るのか?その特徴を以下に紹介していきます。

テスト自動化の開発パラダイムの変換

ScenarioTestを使用すると単体機能の開発段階から自動テストの作成が可能になります。これはアプリケーション開発時や改修時の機能テストと回帰テストの単調な検査作業の繰り返しから開発チームを開放し、大幅な生産性の向上とシステム開発+保守費用の削減、そして開発現場の士気高揚をもたらすことが期待できます。

一般的なテスト自動化の実行サイクル

一般的に新規にWebアプリケーションを作成する場合、自動テストの作成は本体製品のリリースの後に機を見て行います。従って最初のリリース時には結合テスト・システムテストは全て手動で行います。リリースの前後に障害が発生して修正を行う場合、この手動テストの流れをもう一度実行する事になります。その後自動テストを作成しても製品リリースは完了しているため、自動テストは主に回帰テストに使用されることになります。

その後一定の稼働期間を経てこのWebアプリケーションに改修の必要が生じ画面の構成や動作に変更が施される場合、自動テストはかなりの部分が動かなくなる可能性が高まり、結果として再び全てのテストを手動で実行することになります。本番リリース後に自動テストも改修されますが、このサイクルを継続するのに疲弊して自動テストの保守を放棄し結局手動テストに戻ってしまうパターンが多くみられます。

ScenarioTest導入前の開発工数イメージ
問題点① 単体機能の開発や改修時に自動テストを行うことが出来ない。
問題点② 機能改修を行うと、自動テストも改修しないと結合テスト以降ほとんどが手動テストに戻ってしまう。

ScenarioTestの実績に照らすと自動テストでカバーできる比率を全テストカバー範囲4分の3程度まで拡大するとテストに要する時間コストは半分以下に抑えることが可能になります。ただしこのモデルでは自動テストを作成するのは本番リリース後なので、初版開発時や機能改修時には何らテスト工数削減につながるわけではありません。

ScenarioTestを使用した開発段階から自動テストを作成する場合

ScenarioTestを使用して開発段階で自動テストの作成を同時に行うと、この状況は一変します。ScenarioTestはVisual Studioの機能の一部なので開発対象アプリケーションが.NETによるWebアプリケーションであればソリューションの一部を形成することが可能です。これによりアプリケーションの開発と自動テストの開発を同時進行することが可能になり、開発機での単体機能検証時にも自動テストを利用することが出来るようになります。

またScenarioTestにはテスト対象となるWebアプリケーションの配置先の環境に応じてテスト対象ページのURLやページ要素の指定を動的に切り替える仕組みを持っているため、開発時に作成される自動テストはそれ以降のテストフェーズ全体に渡って使用することが可能になります。

ScenarioTest導入後の開発工数イメージ
ScenarioTestを使用すると単体機能開発や改修フェーズでテスト自動化プログラムを開発・メンテナンス出来るため、開発からリリースまで全てのフェーズで自動テストが利用可能になります。

仮に単体機能テストから結合テスト、システムテストまでで総テスト工数が手動テストでは30人日、テスト自動化による時間短縮比率を50%とすると、テスト工数は15人日で済むことになります。
勿論開発時や改修時のメーキング作業の工数は自動テストの作成分増加しますが、テスト工数が浮いた差分で十分ペイ出来ます。しかも今後システム変更や軽微な改修を行った際に実施する回帰テストに利用できるため、運用を含めた作業コストの削減幅は非常に大きくなります。

それではScenarioTestが実際にどういうものなのか、詳しく見ていくことにしましょう。

自動テストの作成

ScenarioTestが便利なのは、まず第1に手軽にテスト自動化用のプログラムがVisual Studio上で作成できることです。必要な拡張機能をダウンロードしてテンプレートからテスト自動化プロジェクトを選択するだけ。あとはMSTestで単体テストを作成するときと似たような手順で自動テストプログラムを作成していくことが出来ます。その手順を以下に紹介しましょう。

手順1.ScenarioTestで自動テストを作成するには、まずVisual Studioの拡張機能の管理メニューより拡張機能の管理画面を表示してScenarioTestを検索してインストールします。

ScenarioTest retrieved in the Visual Studio Extensions administration page.
Visual Studio拡張機能管理画面でScenarioTestを検索するイメージ(現時点では非公開です)

手順2.この結果Visual Studioで新規のプロジェクトを選択する場合にテンプレートの検索条件として言語:C#、環境:Windows、カテゴリー:テストを選択すれば「ScenarioTest.テスト自動化プロジェクト」が検索されるので、これを選択してテスト自動化プロジェクトを作成します。後はプロジェクト内にオプションで配置されるサンプルコード、または製品サイトの技術情報を参考にして、テスト自動化用のコードを作成していきます。

ScenarioTest project template on Template Selector
Visual Studioのプロジェクトテンプレート管理画面。ScenarioTestを検索して選択します。

手順3.テスト自動化用のコードをある程度書き終わったら(1つのWebページの任意のエリアの出力内容のチェックだけでも構いません。)取りあえず実行してみてください。ビルドが通ってデバッグが完了した段階で、Visual Studioのテストメニューより「ScenarioTestの実行」を選択します。テストランナーが起動するので実行したいテストを画面左側のツリー上で選択しテスト実行ボタンをクリックすれば自動テストが開始されます。

ScenarioTest_Running On Windows Launched By Visual Studio
Visual Studioのテストメニューよりテストランナーを起動して選択した自動テストを実行しているところ

ScenarioTestが拡張機能にインストールされていれば、自動テストをテンプレートからの作成して既定で自動的に作成されるサンプル自動テストを実行するまで1分程度しかかかりません。とにかく「直ぐに使える。」かつ「直ぐにテストコードが書ける。」というのが一番大きな特徴です。

高機能なテストランナー

次にScenarioTestのテストランナー画面を紹介します。テストランナーはVisual Studio上でアクティブなソリューションに含まれる全てのScenarioTestのテストメソッド、テストコードを自動的にツリーに表示します。ユーザーはここから任意のテストクラスやテストメソッドを選択して実行します。

テストランナー上ではテストに使用するブラウザとしてPCにインストールされているChrome, Firefox, Microsoft Edgeの何れかを選択できる他、テスト対象プログラムの環境を開発環境、結合テスト環境、システムテス環境など任意の環境を選択することが可能です。(テスト対象となるアプリケーションがそれらの環境にアップされていることが前提です。)

テストが完了すると、テストランナー上には指定されたテストの実行結果レポートが表示されます。各テストメソッドでは拡張WebDriverの働きにより、ScenarioTestが実行した全ての操作がレポート上に「入力エリアAに値BをセットしてボタンCをクリックします。」のように読みやすい文章となって出力されます。

更にScenarioTestがVisual Studioから起動された場合には、レポート上の各行をクリックするとソースファイルの位置にジャンプすることが出来ます。これは検証エラーになった場所や例外がスローされた箇所を探す際に大変便利です。

TestRunner of ScenarioTest, Process log display mode 1
ScenariTestのテストランナー上でテストメソッドの実行レポートを表示させているところ

検証内容については「項目Cに表示されるテキストがDと等しいかチェックします。結果はEでした。」のように検査の内容、期待値と実際値の比較を同様に文章として出力します。またテストレポートでは、個々のテストメソッド、テストクラス、テストソリューション(=Assembly)それぞれの単位で、実行した処理件数や検証の件数と成否の合計を集約して表示します。

TestRunner of ScenarioTest, Result display mode
ScenarioTestのテストレポートでテスト結果の集計を表示しているところ

Selenium WebDriverの拡張

ScenarioTestでは拡張されたSeleniumのWebDriverを使用します。この拡張WebDriverは、操作対象となるWebページ上の要素に対する処理を記録してレポートに出力します。例えば「どの入力エリアにどのような値を設定してどのボタンをクリックしたか?」または「どの出力エリアにはどのような値が出力されたか?」という風に分かりやすい文章で表示します。更にテストレポートにおける検証(Assert)の結果は単に検査の成否だけではなく、検証内容、期待値と実際値をそれぞれ表示します。

またSeleniumではごく稀にではありますがWebDriverで指定したWeb要素のXPathの解析がブラウザの違いによりエラーとなって例外がスローされる場合があります。ScenarioTestではそのような例外に対するハンドリングもフレームワーク内で行っているのでユーザープログラム側でこのような例外に対するハンドリング処理を書く必要はありません。

ScenarioTestでWebアプリケーションのテストプログラムを書く場合はPageObjectModel(POM)パターンに従うことを推奨しており、先ずテスト対象となるページのPageObjectクラスを作成します。このときページ内の要素を拡張されたWebDriverを使用して定義していきます。

下に典型的なPageObjectModelクラスの作成例を示します。(ハイライト部分が拡張WebDriverを使用してWebページの要素を指定している個所です。)

using OpenQA.Selenium;
using EmotionSoft.East.ScenarioTest;

namespace WebPage.Integrated.Tests.SeleniumHQ
{
    public class SeleniumHQTop : ScenarioTestPageObject
    {
        protected override string UrlBase => TestEnvManager.GetUrlBase("HQ");
        protected override string Url => this.UrlBase + "index.html";
        protected override string Alias => "Selenium HQ日本語サイト・トップページ";

        internal ScenarioTestWebElement CommonHeader
        {
            get
            {
                string alias = "共通ヘッダ";
                var xp = "//*[@id=\"header\"]";
                return this.Browser.FindElementEx(By.XPath(xp), alias);
            }
        }

        internal ScenarioTestWebElement HeaderProjectLink
        {
            get
            {
                string alias = "ヘッダ部プロジェクトリンク";
                var xp = "//*[@id=\"menu_projects\"]/a";
                return this.Browser.FindElementEx(By.XPath(xp), alias);
            }
        }

        internal ScenarioTestWebElement HeaderDocumentLink
        {
            get
            {
                string alias = "ヘッダ部ドキュメントリンク";
                var xp = "//*[@id=\"menu_documentation\"]/a";
                return this.Browser.FindElementEx(By.XPath(xp), alias);
            }
        }

        // ・・・ 省略 ・・・

MSTestの拡張

続いてテストプログラム本体の記述方法の説明をします。ScenarioTestは.NETテストフレームワークの定番であるMSTestを拡張して使用しています。従ってVisual Studioの単体テストを書くときと同じ要領でテストプログラムを書いていくことが出来ます。[TestClass]、[TestMethod], [TestInitialize], [TestCleanup]といった基本的なテストプログラム用の属性はそのまま使用することが出来ます。これらにScenarioTest専用の属性を加えることでテストランナーやレポートをより分かりやすいものにします。

ScenarioTestではAssertクラスの拡張を行っています。この中には検証エラーになるとエラー内容を記録してテストを継続する拡張メソッドが用意されています。テストの実行継続に致命的な影響を及ぼさない検証エラーであれば、テスト自体は継続した方が効率的です。検証エラーになった個所はテストレポートで参照することができるので、一通りテストを最後まで実行した後に、まとめてエラーの内容を閲覧することが出来ます。

またScenarioTestにはレポートに任意の情報を出力する様々なメソッドが用意されています。これから行う一連の処理の目的を説明する文章を挿入したり、あるいは一つ一つの操作や検証に任意のIDを与えてレポートに出力することが出来ます。これによりテスターはテストレポートと予め用意したテスト仕様書の検証項目との関連付けが行えるようになります。

using EmotionSoft.East.ScenarioTest;
using STWE = EmotionSoft.East.ScenarioTest.ScenarioTestWebElement;
using System.Drawing;

namespace WebPage.Integrated.Tests.SeleniumHQ
{
    [ScenarioTest]
    [TestClassNote(TestID ="IT01-01",
        Alias ="SeleniumHQのサイトの内容チェックテスト",
        Description = "SeleniumHQのサイトを使用してScenarioTestPageObjectの動作検証を行う。")]
    public class UT_SeleniumHQ: ScenarioTestBase
    {
        [TestInitialize]
        public void SetUp()
        {
            // ブラウザを起動する
            BrowserManager.InitializeBrowser();
        }

        [TestMethod]
        [TestMethodNote(TestCaseID = "TC002",
            Alias = "SeleniumHQのヘッダリンクより「プロジェクト」ページに遷移して内容を調べる。", Description = 
"リンクをクリックして所定のページに遷移した直後にCheckActualUrlをコールするのは定型的なコードになると思われる。")]
        public void ScenarioTestWebElementTest002()
        {
            Signpost("Signpostメソッドの出力内容チェックのための試験(TestCaseID = TC002", Color.Wheat, Color.Blue);
            var hqPage = new SeleniumHQTop();
            hqPage.NavigateToMe();
            hqPage.GetScreenShot("トップページのスクリーンショット");

            // ヘッダ部のプロジェクトリンクをクリック
            SeleniumHQProject nextPage = hqPage.ProjectLinkClick();

            // クリックした結果、正しくプロジェクトページに遷移していれば先の検証を行う。
            if (Assert.That.ExamineSoft(
                nextPage.CompareActualUrl(HttpStatusCheckLevel.Medium), "chkTC002-001"))
            {
                Note("ヘッダ部のプロジェクトリンクによる遷移が成功した後の処理", "wr001",
                    Color.Navy, Color.LightCyan, FontStyle.Italic);
                nextPage.GetScreenShot("プロジェクトページのスクリーンショット");

                Assert.That.Examine(nextPage.Title.Equals("Selenium のプロジェクト"));
                Assert.That.ExamineSoft(nextPage.ContentHedding.Text.Equals("Selenium のプロジェクト"), 
                    "chkTC002-002");

                Note("エラーガイダンスの内容チェック(緩い検証)", "wr002",
                    Color.Navy, Color.LightSalmon, FontStyle.Italic);
                Assert.That.ExamineSoft(nextPage.ErrorContentGuidance.Text.Equals(
                    "Selenium には多数のプロジェクトがあり、これらを組み合わせることで多目的なテスティングシステムを実現しています。"),
                     "chkTC002-003");
                Assert.That.ExamineSoft(nextPage.ContentGuidance.Text.Equals(
                    "Selenium には多数のプロジェクトがあり、これらを組み合わせることで多目的なテスティングシステムを実現しています。"),
                   "chkTC002-004");
            }
        }

        // ・・・ 省略 ・・・

自動テストの実行方式

テスト自動化プロジェクトは以下の2つの方法の何れかの方法で実行する事が出来ます。

ScenarioTestをWidowsアプリケーションとしてビルドして実行する。

ScenarioTestのプロジェクトテンプレートで作成されたテスト自動化プロジェクトはWindowsFormsアプリケーションになっており、テストランナーが起動画面になります。テストランナーは既定ではアセンブリー内のScenarioTestプログラムを自動的に検索して実行可なテストプログラムを画面左側のツリーにリストします。ここから任意のテストクラスやテストメソッドを選択して実行します。

Visual Studioのテストメニューより実行する。

拡張機能でScenarioTestをインストールすると、自動的にテストメニューの下に「ScenarioTestの起動」サブメニューが追加されます。このサブメニューをクリックすると、テストランナーが起動してカレントソリューション内の全てのScenarioTestプログラムを自動的に検索して上と同様画面左側のツリーにリストします。


つまりアプリケーションとしてビルドして実行してもVisual Studioのメニューから実行してもScenarioTestの挙動は変わりません。何れの場合もテストランナーが起動して自由に任意のテストを選択して実行する事が出来ます。唯一違うのは、前者の場合 自動テストアプリケーションを生成することです。生成されたアプリケーションは単体で実行される通常のWindowsFormsアプリケーションなので、例えば運用チームに配布してシステム設定を変更した時の回帰テストに使用してもらう、といった利用方法が考えられます。

  • 勿論ScenarioTestはこのツールを使用して作成したアプリケーションに対しては何らライセンスを要求することはありません。

リリーススケジュール

2021年秋に1stバージョンのリリースを予定しています。
また、ScenarioTestはその後、次のような機能改善を加えてくロードマップを描いています。

  • .NET 5.0への対応
  • Appiumへの対応
  • Windows アプリケーションへの対応
  • PageObjectModelのGUIからの設定を可能にする機能の追加
  • ・・・・

少し先になるかもしれませんが、楽しみにしていてくださいね。