使用TransactionScope在specflow UI测试后进行清理

时间:2013-07-26 07:08:22

标签: entity-framework selenium-webdriver integration-testing transactionscope specflow

我有一个遗留的ASP.NET 4.0 WebForms应用程序,我想为其构建一些端到端测试。我使用Specflow创建测试,使用Selenium WebDriver编写Firefox脚本。

应用程序使用简单的ADO.NET访问数据库(MS SQL Server 2008 R2 SP1)。

我想实现测试隔离,所以一个测试在数据库中写入的所有内容我希望它在测试结束时删除,所以我使用以下方法:

        [BeforeScenario]
        public void ScenarioSetup()
        {

            Scope = new TransactionScope(TransactionScopeOption.RequiresNew,
                                         new TransactionOptions {IsolationLevel =    IsolationLevel.ReadUncommitted});
            Browser.CreateNew();
        }

        [AfterScenario]
        public void ScenarioCleanup()
        {
            if (Scope != null)
            {
                Scope.Dispose();
            }
            Browser.Close();
        }

因此,打开一个交易范围并在最后处置它。

Given 块中,我打开一个EF5 DbContext并写一些设置数据:

  public void GivenIHaveAccountsWithDifferentStatusesInTheSystem()
    {
        using (var ctx = new WorkflowImprovementsContext())
        {
            try
            {
                _contact = new Contact()
                {
                    created = new DateTime(2010, 1, 18),
                    countryId = 1,
                    stateId = 1,
                    contactName = "Account Contact Name One",
                    companyName = "Company Company Account One",
                    address1 = "Address 1 One",
                    address2 = "Address 2 One",
                    city = "City Account One",
                    email = "Email Account One",
                    zipCode = "A123",
                    phone = "0735352244",
                    mobile = "0735352244",
                    pager = "0735352244",
                    fax = "0735352244",
                    webSite = "www.test.com"
                };
                ctx.Contacts.Add(_contact);

                ctx.SaveChanges();

            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.Message + ex.StackTrace);
            }

        }

请注意,上下文在使用后会被处理掉。

我使用ReSharper测试运行器运行我的specflow测试。在测试的 When 步骤中的某个时刻的测试启动Firefox(单独的进程)并脚本浏览器转到一个页面,在那里通过AJAX调用刚刚放入DB的数据正在阅读。

这是我被困住的地方,AJAX调用不会返回(它后面的Web服务中的代码等待数据库访问),直到我处理了TransactionScope。

为什么Firefox进程中的应用程序无法读取测试运行程序进程中写入的数据? (TS是ReadUncommitted,我尝试了所有其他但仍然没有运气)

我之前无法处理范围,因为这会破坏目的,我需要在读取数据之后再进行断言然后处理TS并随之将数据库中的数据回滚。

1 个答案:

答案 0 :(得分:1)

这听起来像是在尝试在打开的事务中在数据库中创建数据,并在事务仍处于打开状态且未提交时从不同进程中的不同事务中读取相同的数据。这不适用于事务范围的默认隔离级别。除非您在应用程序中使用ReadUncommitted或对应用程序中的查询使用nolock提示,否则在事务提交之前您将无法读取该信息。

您可能不希望允许应用程序读取未提交的数据 - 这就是关系数据库遵循ACID属性并使用事务的原因。如果您可以阅读未提交的信息,则可能会在您的应用程序中发生错误。这对你的应用程序来说可能没问题 - 但是如果它不是你正在做的事情,因为你的应用程序应该这样做,我不建议只为测试而做。

我从来都不喜欢使用事务来删除测试中的数据 - 似乎是以一种他们并非真正意图和混乱的方式使用事务。在单个流程中,您可以在一个单独的事务中完成所有测试设置和拆卸以及应用程序代码执行的所有操作,但是即使在那里我也不会为此疯狂。

实际上,你可能会过度思考并使这个过于困难。如果你想要的是在执行测试中的操作之前创建数据并在之后删除它们,也许你应该做最简单的事情,只需添加之前和之后删除。我更喜欢你正在做的事情,你实际上是在一个过程边界上击中应用程序。