使用 NUnit Test Runner 測試命令和導航的簡單 Specflow

我們為什麼需要這個?

目前在 Xamarin.Forms 中進行單元測試的方法是通過平臺執行,因此你的測試必須在 ios,android,windows 或 mac UI 環境中執行在 IDE 中執行測試

Xamarin 還使用 Xamarin.TestCloud 產品提供了令人敬畏的 UI 測試,但是當想要實現 BDD 開發實踐,並且能夠測試 ViewModel 和 Commands,同時在本地或構建伺服器上的單元測試執行器上廉價執行時,沒有建成的方式。

我開發了一個庫,允許使用 Specflow 和 Xamarin.Forms 輕鬆實現從 Scenarios 定義到 ViewModel 的功能,獨立於用於 App 的任何 MVVM 框架(例如 XLabsMVVMCrossPrism

如果你是 BDD 的新手 ,請檢查 Specflow out。

用法:

  • 如果你還沒有,請從此處(或從你的 visual studio IDE)安裝 specflow visual studio 擴充套件: https ://visualstudiogallery.msdn.microsoft.com/c74211e7-cb6e-4dfa-855d-df0ad4a37dd6

  • 將類庫新增到 Xamarin.Forms 專案中。那是你的測試專案。

  • nuget 中的 SpecFlow.Xamarin.Forms 包新增到你的測試專案中。

  • 向你繼承 TestApp 的測試專案新增一個類,並註冊你的 views / viewmodels 對以及新增任何 DI 註冊,如下所示:

    public class DemoAppTest : TestApp
    {
        protected override void SetViewModelMapping()
        {
            TestViewFactory.EnableCache = false;

            // register your views / viewmodels below
            RegisterView<MainPage, MainViewModel>();
        }

        protected override void InitialiseContainer()
        {
            // add any di registration here
            // Resolver.Instance.Register<TInterface, TType>();
            base.InitialiseContainer();
        }
    }
  • 將 SetupHook 類新增到測試專案中,以便為你新增 Specflow 掛鉤。你將需要按照以下方式引導測試應用程式,提供你在上面建立的類以及你的應用程式初始檢視模型:
    [Binding]
    public class SetupHooks : TestSetupHooks
    {   
        /// <summary>
        ///     The before scenario.
        /// </summary>
        [BeforeScenario]
        public void BeforeScenario()
        {
            // bootstrap test app with your test app and your starting viewmodel
            new TestAppBootstrap().RunApplication<DemoAppTest, MainViewModel>();
        }
    }
  • 你需要在你的 xamarin.forms 檢視程式碼隱藏中新增一個 catch 塊,以便忽略 xamarin.forms 框架,迫使你執行 app ui(我們不想做的事情):
        public YourView()
        {
            try
            {
                InitializeComponent();
            }
            catch (InvalidOperationException soe)
            {
                if (!soe.Message.Contains("MUST"))
                    throw;
            }
        }
  • 為專案新增 specflow 功能(使用 vs specflow 擴充套件附帶的 vs specflow 模板)

  • 建立/生成繼承 TestStepBase 的步驟類,將 scenarioContext 引數傳遞給基類。

  • 使用導航服務和幫助程式來導航,執行命令和測試檢視模型:

  [Binding]
    public class GeneralSteps : TestStepBase
    {
        public GeneralSteps(ScenarioContext scenarioContext)
            : base(scenarioContext)
        {
            // you need to instantiate your steps by passing the scenarioContext to the base
        }

        [Given(@"I am on the main view")]
        public void GivenIAmOnTheMainView()
        {
            Resolver.Instance.Resolve<INavigationService>().PushAsync<MainViewModel>();           
            Resolver.Instance.Resolve<INavigationService>().CurrentViewModelType.ShouldEqualType<MainViewModel>();
        }
        
        [When(@"I click on the button")]
        public void WhenIClickOnTheButton()
        {
            GetCurrentViewModel<MainViewModel>().GetTextCommand.Execute(null);
        }

        [Then(@"I can see a Label with text ""(.*)""")]
        public void ThenICanSeeALabelWithText(string text)
        {           
            GetCurrentViewModel<MainViewModel>().Text.ShouldEqual(text);
        }
    }