其實是這兩天突然有的想法,於是想說來做一下驗証,順便練一下功。

雖然使用了 SpecFlow + Selenium ,但這其實不是 BDD,流程有點反過來,我先寫好標的的 API,再回過頭使用 SpecFlow 來建立整合測試的案例。

會有這想法,主要是考慮到 Web API 在執行上,相對一般的互動網頁來說,比較單純,使用 Selenium 來操作存取 API 應該也會比較簡單。至少可以不用 Selenium IDE 來錄製情境,單純的寫 code 應該就可以了。

在這次測試的經驗上來說,應該也算是証實了我的想法。整段連結 API 跟取結果的測試程式相當簡單,單純到如果要找人接手,接手的人應該也不會看不懂的程度。

只是有個需要再思考的議題是,雖然我在 Feature 檔中寫的預期結果是數字 7,但 Web API 回傳的值其實是 XML 或 JSON,所以我目前在 Assert 結果上,是直接拿 XML 碼來做比對。這部份的可讀性要怎麼改善,可能就需要再想想了。

測試的標的很簡單,我寫了一個很單純的計算機 Calculator API,裡頭單純只做數值相加的計算。程式碼如下︰

namespace TestApi.Controllers
{
    public class CalculatorController : ApiController
    {
        [HttpGet]
        public int Add(int number1, int number2)
        {
            return number1 + number2;
        }
    }
}

使用 SpecFlow 建立的 Feature 檔如下︰

Feature: Calculator API
    In order to 提供使用者數值計算能力
    As a API 使用者
    I want to 一個 API,可以告訴我數值計算的結果

Scenario: 兩個數值相加
    Given 有以下值要計算︰
    | number1 | number2 |
    | 3       | 4        |
    When 將值傳送給 API 做計算
    Then API 回傳值為 7 

展開後修改的 Step 檔如下︰

using System;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using OpenQA.Selenium;
using OpenQA.Selenium.Firefox;
using TechTalk.SpecFlow;

namespace TestApi.Spec
{
    [Binding]
    public class CalculatorAPISteps
    {
        private IWebDriver driver;

        [BeforeScenario()]
        public void Setup()
        {
            driver = new FirefoxDriver();
        }

        [AfterScenario()]
        public void TearDown()
        {
            driver.Quit();
        }

        [Given(@"有以下值要計算︰")]
        public void Given有以下值要計算(Table table)
        {
            ScenarioContext.Current.Add("Number1", Convert.ToInt32(table.Rows[0]["number1"]));
            ScenarioContext.Current.Add("Number2", Convert.ToInt32(table.Rows[0]["number2"]));
        }
        
        [When(@"將值傳送給 API 做計算")]
        public void When將值傳送給API做計算()
        {
            int number1 = ScenarioContext.Current.Get<int>("Number1");
            int number2 = ScenarioContext.Current.Get<int>("Number2");

            driver.Navigate().GoToUrl("http://localhost:7070/Api/Calculator/Add?number1=" + number1 + "&number2=" + number2);
            string response = driver.PageSource;
            ScenarioContext.Current.Add("Response", response);
        }
        
        [Then(@"API 回傳值為 (.*)")]
        public void ThenAPI回傳值為(int result)
        {
            string actual = ScenarioContext.Current.Get<string>("Response");
            string expected ="<int xmlns=\"http://schemas.microsoft.com/2003/10/Serialization/\">" + result + "</int>";

            Assert.AreEqual(expected, actual);
        }
    }
}

測試程式碼可在這裡下載︰TestApi.zip

簡單筆記一下 :)