【C#】Selenium用のデモサイトを使ってSeleniumを動かしてみた

# 初めに
Seleniumユーザーコミュニティが用意している[デモサイト](http://www.selenium.jp/test-site)を使ってSeleniumのテストコードを動かしてみた。
以下、その記録。

# 前提条件
- Windows 10
- C#
- Visual Studio 2017

# 内容
##プロジェクトを作る
Visual Studioを起動して「ファイル>新規作成>プロジェクト」と選択して、単体テストプロジェクトを作成する。
![無題.png](https://qiita-image-store.s3.amazonaws.com/0/178845/d788d4b2-22df-76a1-23b1-88487b2b43c8.png)

NuGenパッケージマネージャーを使って下記の５つをプロジェクトに導入する。

- Selenium.WebDriver
- Selenium.Chrome.WebDriver
- NUnit
- NUnit.COnsole
- NUnit3TestAdapter

##ページオブジェクトを作る
###予約フォーム画面

```ReserveFormPage.cs
    class ReserveFormPage
    {
　　　　 // フォームに値を設定する
        public static void SetForm(IWebDriver driver)
        {
            // フォームを初期化
            driver.FindElement(By.Id("reserve_year")).Clear();
            driver.FindElement(By.Id("reserve_month")).Clear();
            driver.FindElement(By.Id("reserve_day")).Clear();
            driver.FindElement(By.Id("reserve_term")).Clear();
            driver.FindElement(By.Id("headcount")).Clear();
            driver.FindElement(By.Id("guestname")).Clear();

            // 予約日時(翌日)を設定
            DateTime tommorow = DateTime.Now.AddDays(1);
            driver.FindElement(By.Id("reserve_year")).SendKeys(tommorow.Year.ToString());
            driver.FindElement(By.Id("reserve_month")).SendKeys(tommorow.Month.ToString());
            driver.FindElement(By.Id("reserve_day")).SendKeys(tommorow.Day.ToString());

            // 宿泊日数
            driver.FindElement(By.Id("reserve_term")).SendKeys(1.ToString());

            // 宿泊人数
            driver.FindElement(By.Id("headcount")).SendKeys(1.ToString());

            // 朝食
            driver.FindElement(By.Id("breakfast_on")).Click();

            // プラン
            driver.FindElement(By.Id("plan_b")).Click();

            // 代表者氏名
            driver.FindElement(By.Id("guestname")).SendKeys("たろう");
        }

　　　　 // 予約日時のフォームに値を設定する
        public static void SetForm_RserveDate(IWebDriver driver, DateTime dt)
        {
            driver.FindElement(By.Id("reserve_year")).Clear();
            driver.FindElement(By.Id("reserve_month")).Clear();
            driver.FindElement(By.Id("reserve_day")).Clear();

            driver.FindElement(By.Id("reserve_year")).SendKeys(dt.Year.ToString());
            driver.FindElement(By.Id("reserve_month")).SendKeys(dt.Month.ToString());
            driver.FindElement(By.Id("reserve_day")).SendKeys(dt.Day.ToString());
        }

　　　　 // 予約者のフォームに値を設定する
        public static void SetForm_GuestName(IWebDriver driver,string name)
        {
            driver.FindElement(By.Id("guestname")).Clear();
            driver.FindElement(By.Id("guestname")).SendKeys(name);
        }

　　　　 // 次へボタンを押下する
        public static void ClickNextBtn(IWebDriver driver)
        {
            driver.FindElement(By.Id("goto_next")).Click();
        }
    }
```
### 予約確認画面

```ReserveConfirmPage.cs
    class ReserveConfirmPage
    {
　　　　 // 確認ボタンを押下する
        public static void ClickConfirmBtn(IWebDriver driver)
        {
            driver.FindElement(By.Id("commit")).Click();
        }

　　　　 // 戻るボタンを押下する
        public static void ClickBackBtn(IWebDriver driver)
        {
            driver.FindElement(By.Id("returnto_index")).Click();
        }

　　　　 // 画面に表示されている「予約者名」を取得する
        public static string GetGuestName(IWebDriver driver)
        {
            return driver.FindElement(By.Id("gname")).Text;
        }
    }
```

### 予約完了画面

```ReserveCompletePage.cs
    class ReserveCompletePage
    {
　　　　 // 画面に表示されているメッセージを取得する
        public static string GetMessage(IWebDriver driver)
        {
            return driver.FindElement(By.XPath("/html/body/div[1]/h1")).Text;
        }
    }
```

### エラー画面

```ErrorPage.cs
    class ErrorPage
    {
　　　　 // 画面のタイトルを取得する
        public static string GetPageTitle(IWebDriver driver)
        {
            return driver.Title;
        }

　　　　 // 画面に表示されている詳細エラーメッセージを取得する
        public static string GetErrorDetail(IWebDriver driver)
        {
            return driver.FindElement(By.Id("errorcheck_result")).Text;
        }
    }
```

## テストコードを作る

```ReservationTest.cs
    [TestFixture]
    public class ReservationTest
    {
        private  IWebDriver d;

        [SetUp]
        public void SetUp()
        {
            this.d = new ChromeDriver();
            d.Url = "http://example.selenium.jp/reserveApp/";
        }

        [TearDown]
        public void TearDown()
        {
            this.d.Quit();
        }

        /// <summary>
        /// 予約画面で正しい情報を入力して、予約完了まで行けることを確認するテスト
        /// </summary>
        [TestCase()]
        public void BasicReservationTest()
        {
            // 予約入力画面
            ReserveFormPage.SetForm(d);
            ReserveFormPage.ClickNextBtn(d);

            // 予約確認画面
            ReserveConfirmPage.ClickConfirmBtn(d);

            // 予約完了画面
            Assert.AreEqual(ReserveCompletePage.GetMessage(d), "予約を完了しました。");
            
        }

        /// <summary>
        /// 過去日で予約しようとして、エラー画面に遷移するテスト
        /// </summary>
        [TestCase()]
        public void ReservationForPastDaysTest()
        {
            DateTime past_day = DateTime.Now.AddDays(-1);

            // 予約入力画面
            ReserveFormPage.SetForm(d);
            ReserveFormPage.SetForm_RserveDate(d, past_day);
            ReserveFormPage.ClickNextBtn(d);

            // エラー画面
            Assert.AreEqual(ErrorPage.GetPageTitle(d), "予約エラー");
            Assert.AreEqual(ErrorPage.GetErrorDetail(d), "宿泊日には、翌日以降の日付を指定してください。");

        }


        /// <summary>
        /// 予約情報を入力して確認画面にいって、もう一度入力画面に戻って予約者の名前を変更して、再度確認画面に行って予約を確定するテスト
        /// </summary>
        [TestCase()]
        public void BackwardAndForwardTest()
        {

            // 予約画面操作
            ReserveFormPage.SetForm(d);
            ReserveFormPage.SetForm_GuestName(d, "たろう");
            ReserveFormPage.ClickNextBtn(d);

            // 予約確認画面操作
            ReserveConfirmPage.ClickBackBtn(d);


            // 予約画面操作
            ReserveFormPage.SetForm(d);
            ReserveFormPage.SetForm_GuestName(d,"やまだたろう");
            ReserveFormPage.ClickNextBtn(d);

            // 予約確認画面操作
            ReserveConfirmPage.ClickConfirmBtn(d);

            // 予約完了画面操作
            Assert.AreEqual(ReserveCompletePage.GetMessage(d), "予約を完了しました。");
        }
    }
```

## 動かす
Visual Studioから単体テストコードを実行する。
テスト結果がすべてGreenになればOK。

![無題2.png](https://qiita-image-store.s3.amazonaws.com/0/178845/17732760-212a-9c7e-0a68-727d7f9bf72f.png)


## 最後に
ページオブジェクトの各種メソッドは、あえてstaticにしてみた。
呼び出す側にコンストラクタを書かなくていい分、テストコード側がすっきりする気がしたので。

以上