取消测试后清理

时间:2015-06-11 16:51:27

标签: c# visual-studio visual-studio-2013 mstest specflow

我目前正在通过visual studio运行测试。在运行所有测试之前,我会自动创建一组具有已知凭据的用户,并在运行结束时删除这些用户。但是,有时我需要在中途取消我的测试。在这些情况下,测试永远不会有机会进行清理,这意味着测试运行中遗留了虚假的用户信息,并可能导致下一次测试运行崩溃(当它尝试将用户信息添加到数据库中时)。无论如何,即使测试被取消,还是强制visual studio / mstest运行清理方法?

我知道一个选项是进行测试检查并确保用户信息不存在,如果确实在创建新用户之前删除了它。但这仍然无法解决取消测试运行的问题,从而留下不需要的测试数据。

更新

对于错误传达感到抱歉,但是在测试开始时清理数据不是一种选择。我给出了一个非常简单的问题视图,但简单地说,我没有简单的方法来确保在测试开始时不存在测试数据。所有清理必须在测试结束时进行。

9 个答案:

答案 0 :(得分:9)

这是不可能的。您最好找到一个替代解决方案,例如使用单独的数据库在每次测试运行之前测试和清理所有数据,使用固定的测试用户集或使用某个标记标记测试数据。查看吉米·博加德的RelativeSource文章。

没有内置方法可以更改MSTest默认行为。从理论上讲,您可以使用Isolating database data in integration tests事件编写MSTest扩展,但这不是一个简单的过程,需要更改注册表。此外,很多人抱怨它不起作用。

还有MSTest V2,一个新版本的MSTest,具有新的可扩展性点。但看起来你不能用这个点改变取消行为,只写属性装饰器。见TestExecution.OnTestStopping

您无法使用Process.GetCurrentProcess().Exitedint main() { Foo* foo = new Foo(); // The process is being brutally kill here. (kill -9 or Windows equivalent) delete foo; return 0; } 事件,因为取消似乎会阻止测试运行进程。

NUnit目前也不支持此功能。请参阅相关的NUnit测试适配器Extending MSTest V2问题。

答案 1 :(得分:7)

我不是在测试结束时调用清理函数,而是在每次测试开始时调用我的,以解决这个问题。

答案 2 :(得分:5)

在创建数据之前执行清理,这将确保您无论发生什么都没有剩余数据。当然,只有在运行设置之前能够识别任何剩余数据时才能实现这一点。

答案 3 :(得分:4)

这个想法是在测试开始之前初始化事务。为了将数据保存在数据库中,必须提交事务,但从不提交事务。在测试停止时,如果测试成功或不成功,则适用。

在集成测试中,我们使用这样的东西(使用NUnit)(它是真正的生产代码)

public class RollbackAttribute : TestAttribute, ITestAction
{
    private TransactionScope _transaction;

    public void BeforeTest(ITest test)
    {
        _transaction = new TransactionScope();
    }

    public void AfterTest(ITest test)
    {
        _transaction.Dispose();
    }

    public ActionTargets Targets => ActionTargets.Test;
}

[TestFixture]
public class SomeTestClass
{
    [Rollback] //No need [Test] because Rollback is inherit it.
    public void SomeTestMethod()
    {
    }
}

在MsTest上你可以做类似的事情,但在这种情况下你应该从基类继承,我希望它有效。例如:

public class RollbackTestBase
{
    private TransactionScope _transaction;

    [TestInitialize]
    public virtual void Setup()
    {
        _transaction = new TransactionScope();
    }


    [TestCleanup]
    public virtual void TearDown()
    {
        _transaction.Dispose();
    }
}

[TestClass]
public class IntegrationTest : RollbackTestBase
{
    [TestMethod]
    public void TestDataBase()
    {
        Assert.IsTrue(true);
    }

    [TestInitialize]
    public virtual void Init()
    {
    }

    [TestCleanup]
    public virtual void CleanUp()
    {
    }
}

答案 4 :(得分:3)

我认为你应该在测试,创建数据和完成测试之前打开一个事务。但是不要提交交易。这将确保测试根本不会影响您的数据库。

<强>更新 更简单的方法是使用docker容器。 您可以从映像运行容器,并在测试完成后删除该容器。这绝对可以降低测试的复杂性。

答案 5 :(得分:3)

在ATP中分配资源时,我们需要考虑两种情况(资源可能是创建用户,与数据库连接)。他们是

  • 每次测试后创建和删除资源。
  • 经过一系列测试后创建和删除资源。

每次测试后创建和删除资源:

如果我们想在执行 a 测试之前创建特定对象的实例,并希望在执行该测试后清理分配给该对象的内存,那么我们使用Test SetUp和{ {1}} NUnit的属性。在您的情况下,对象是创建用户数。

Test TearDown:用 Test SetUp 属性修饰的函数包含在执行任何测试之前执行的代码段。

[SetUp]:用 Test TearDown 属性修饰的函数包含在执行任何测试后执行的代码段

实施:

[TearDown]

在完成一组测试后创建和删除资源:

现在,如果我们要为测试集创建对象的实例,并希望在执行所有测试后清理内存,则[TestClass] public class UnitTest1 { [SetUp] public void SetUP() { // Creating Users with proper credentials } [TestMethod] public void TestMethod1() { //Write your ATP } [TearDown] public void TearDown() { //Clean up } } [TestFixtureSetUp]初始化对象和分别清理内存。再次在您的情况下,对象可以创建一组用户。

[TestFixureTearDown]:使用[TestFixtureSetUp]修饰的函数将在执行执行一组测试之前执行一次。

TestFixtureSetUp:用[TestFixtureTearDown]修饰的函数将在执行一组测试后执行

实施

TestFixtureTearDown

注意:我会建议您,如果您尝试创建和删除特定ATP的用户,请选择[TestFixture] public class Tests { [TestFixtureSetUp] public void Setup() { //Create users with credentials } [Test] public void _Test1() { //Test_1 } [Test] public void _Test2() { //Test2 } [TestFixtureTearDown] public void CleanUp() { //Cleanup; Here you need to add code to Delete all users } } SetUp。如果您尝试使用相同的ATP,我建议您使用TearDownTestFixtureSetUp

&#34;如果您的测试通过或失败,SetUp和TearDown函数将执行&#34;

参考文献:

答案 6 :(得分:2)

Visual Studio因此使用NUNIT,您可以使用TearDownAttribute。它应该在测试后运行,即使测试被取消。您可以编写一个函数来清理数据。

请在此处阅读参考文档:http://nunit.org/docs/2.2/teardown.html

答案 7 :(得分:2)

了解有关NUNIT标准的更多信息。请按照Test类中的步骤进行操作:

[TestFixture]
public class _TestClass
{
        [TestFixtureSetUp]
        public void Setup()
        {
           //Clearup can be here before start of the tests. But not Recommended
        }

        [Test]
        public void _Test1()
        {
        }
        [Test]
        public void _Test2()
        {
        }

        [TestFixtureTearDown]
        public void CleanUp()
        {
            //I will recommend to clean up after all the tests complete
        }
}

参考:http://nunit.org/docs/2.5/fixtureTeardown.html

答案 8 :(得分:2)

使用所谓的&#34;数据库模拟&#34;更好地解决问题的方法。在这种情况下,您可以使用不同的数据库(或虚假的虚拟数据库)运行测试。

本文解释了如何在C#中实现它 https://msdn.microsoft.com/en-us/library/ff650441.aspx