(无头文件)asp.net mvc / webapi集成测试框架5

我目前正在研究(理想的是无头的)asp.net mvc 5集成测试框架(可能在同一个项目中使用webapi)。 我知道这些2:

  • SpecsFor.Mvc
  • MvcIntegrationTestFramework(这在github上有几个化身)
  • 还有其他人吗? 我特别感兴趣的是可以与specflow很好地协作的框架。


    我今天成功地将SpecsFor.Mvc与SpecFlow集成在一起。 它太酷了。

    这里有一组类可以让你开始将SpecsFor.Mvc与SpecFlow集成起来。 当然,这些可以更好地抽象和延伸; 但最低限度,这是你所需要的一切:

    namespace SpecsForMvc.SpecFlowIntegration
    {
        using Microsoft.VisualStudio.TestingTools.UnitTesting;
        using SpecsFor.Mvc;
        using TechTalk.SpecFlow;
    
        [Binding]
        public class SpecsForMvcSpecFlowHooks
        {
            private static SpecsForIntegrationHost integrationHost;
    
            /// <summary>
            /// <p>
            /// This hook runs at the end of the entire test run.
            /// It's analogous to an MSTest method decorated with the
            /// <see cref="Microsoft.VisualStudio.TestingTools.UnitTesting.AssemblyCleanupAttribute" />
            /// attribute.
            /// </p>
            /// <p>
            /// NOTE: Not all test runners have the notion of a test run cleanup.
            /// If using MSTest, this probably gets run in a method decorated with
            /// the attribute mentioned above. For other test runners, this method
            /// may not execute until the test DLL is unloaded. YMMV.
            /// </p>
            /// </summary>
            [AfterTestRun]
            public void CleanUpTestRun()
            {
                integrationHost.Shutdown();
            }
    
            /// <summary>
            /// <p>
            /// This hook runs at the beginning of an entire test run.
            /// It's equivalent to an MSTest method decorated with the
            /// <see cref="Microsoft.VisualStudio.TestTools.UnitTesting.AssemblyInitializeAttribute />
            /// attribute.
            /// </p>
            /// <p>
            /// NOTE: Not all test runners have a notion of an assembly
            /// initializer or test run initializer, YMMV.
            /// </p>
            /// </summary>
            [BeforeTestRun]
            public static void InitializeTestRun()
            {
                var config = new SpecsForMvcConfig();
    
                config.UseIISExpress()
                    .With(Project.Named("Your Project Name Here"))
                    .ApplyWebConfigTransformForConfig("Debug");
    
                config.BuildRoutesUsing(r => RouteConfig.RegisterRoutes(r));
    
                // If you want to be authenticated for each request, 
                // implement IHandleAuthentication
                config.AuthenticateBeforeEachTestUsing<SampleAuthenticator>();
    
                // I originally tried to use Chrome, but the Selenium 
                // Chrome WebDriver, but it must be out of date because 
                // Chrome gave me an error and the tests didn't run (NOTE: 
                // I used the latest Selenium NuGet package as of
                // 23-08-2014). However, Firefox worked fine, so I used that.
                config.UseBrowser(BrowserDriver.Firefox);
    
                integrationHost = new SpecsForMvcIntegrationHost(config);
                integrationHost.Start();
            }
    
            /// <summary>
            /// This hook runs once before any of the SpecFlow feature's
            /// scenarios are run and stores a <see cref="SpecsFor.Mvc.MvcWebApp />
            /// instance in the <see cref="TechTalk.SpecFlow.FeatureContext" />
            /// for the feature.
            /// </summary>
            [BeforeFeature]
            public static void CreateFeatureMvcWebApp()
            {
                MvcWebApp theApp;
                if (!FeatureContext.Current.TryGetValue<MvcWebApp>(out theApp))
                    FeatureContext.Current.Set<MvcWebApp>(new MvcWebApp());
            }
        }
    
        public class SpecsForMvcStepDefinitionBase
        {
            /// <summary>
            /// Gets the instance of the <see cref="SpecsFor.Mvc.MvcWebApp" />
            /// object stored in the <see cref="TechTalk.SpecFlow.FeatureContext" />
            /// for the current feature.
            /// </summary>
            public static MvcWebApp WebApp
            {
                get { return FeatureContext.Current.Get<MvcWebApp>(); }
            }
        }
    }
    

    然后,假设您有一个SpecFlow功能文件,如下所示(这是部分文件):

    Feature: Login
        As a user of the website
        I want to be able to log on the the site
        in order to use the features available to site members.
    
    # For the site I'm currently working with, even though it's MVC, it's more
    # of a WebAPI before there was WebAPI--so the controllers accept JSON and return
    # JsonResult objects--so that's what you're going to see.
    Scenario: Using a valid username and password logs me on to the site
        Given the valid username 'somebody@somewhere.com'
        And the password 'my_super_secure_password'
        When the username and password are submitted to the login form
        Then the website will return a result
        And it will contain an authentication token
        And it will not contain any exception record.
    

    现在针对上述场景的步骤如下:

    using Newtonsoft.Json;
    using OpenQA.Selenium;
    using MyWebSite.Controllers;
    using Should;
    using TechTalk.SpecFlow;
    
    [Binding]
    public class LoginSteps : SpecsForMvcStepDefinitionBase
    {
        // The base class gets me the WebApp property that allows easy
        // access to the SpecsFor.Mvc.MvcWebApp object that drives a web browser
        // via Selenium.
    
        private string _username;
        private string _password;
        private string _portalSessionId;
        private ServiceResponse<LoginSummary> _loginResponse;
    
        [Given(@"the valid username '(.*)'")]
        [Given(@"the invalid username '(.*)'")]
        public void GivenAUsername(string username)
        {
            _username = username;
        }
    
        [Given(@"the valid password '(.*)'")]
        [Given(@"the invalid password '(.*)'")]
        public void GivenAPassword(string password)
        {
            _password = password;
        }
    
        [When(@"the username and password are submitted to the " +
              @"LoginUser action method of the UserController")]
        public void WhenTheUsernameAndPasswordAreSubmitted()
        {
            WebApp.NavigateTo<UserController>(
                c => c.LoginUser(_username, _password)
            );
        }
    
        [Then(@"the UserController will reply with a LoginSummary")]
        public void ThenTheUserControllerWillReplyWithALoginSummary()
        {
            _loginResponse = 
                JsonConvert.DeserializeObject<ServiceResponse<LoginSummary>>(
                    WebApp.Browser.FindElement(By.TagName("pre")).Text
            );
        }
    
        [Then(@"it will contain an authentication token")]
        public void ThenItWillContainAnAuthenticationToken()
        {
            _loginSummary.Results.Count.ShouldBeGreaterThan(0);
            _loginSummary.Results[0].AuthenticationToken.ShouldNotBeEmpty();
        }
    
        [Then(@"it will not contain an exception record")]
        public void THenItWillNotContainAnExceptionRecord()
        {
            _loginSummary.Exception.ShouldBeNull();
        }
    }
    

    很酷。

    关于用BeforeTestRunAfterTestRun装饰的方法,我在以下博客文章中找到了代码注释中提到的信息:Advanced SpecFlow:使用钩子运行附加自动化代码。

    当然,如果您要测试演示文稿布局,您可能仍然希望构建遵循页面对象模式的类。 正如我在我的代码评论中所述,我正在编写针对WebAPI之前的集成测试的特定应用程序,但功能类似于WebAPI,但使用ASP.Net MVC。 我们尚未将其正式移植到WebAPI。

    链接地址: http://www.djcxy.com/p/22131.html

    上一篇: (headless) integration testing frameworks for asp.net mvc/webapi 5

    下一篇: Prevent history propagation to the parent window