Модульный тест не соответствует результату или не пройден - PullRequest
0 голосов
/ 16 мая 2011

Один из моих модульных тестов, кажется, случайно проходит или не проходит при запуске. Единственная вещь, которая имеет смысл для меня, почему это происходит, если данные в базе данных переходят в другое состояние при каждом запуске теста, но я использую транзакции для отката базы данных в каждом тесте - если только он работает неправильно , Вот мой базовый класс модульных тестов и класс модульных тестов, в которых возникла проблема. Можете ли вы увидеть что-то, чего мне не хватает, или что еще мне нужно искать?

Это происходит с TestDriven.Net и модульным тестовым каркасом Visual Studio.

Partial Public MustInherit Class TestBase

    Private _scope As Transactions.TransactionScope

    <DebuggerStepThrough()> _
    <TestInitialize()> _
    Public Sub Setup()

            //'Start the Distribution Transaction Coordinator, if it's not already running.
            Using dtcService As New System.ServiceProcess.ServiceController("Distributed Transaction Coordinator", My.Computer.Name)
                    If dtcService.Status = ServiceProcess.ServiceControllerStatus.Stopped Then
                            dtcService.Start()
                    End If
            End Using

            _scope = New TransactionScope(TransactionScopeOption.RequiresNew, New TimeSpan(0))
    End Sub

    <DebuggerStepThrough()> _
    <TestCleanup()>
    Public Sub Teardown()
        If _scope IsNot Nothing Then
            _scope.Dispose()
        End If
    End Sub

    <System.Diagnostics.DebuggerStepThrough()> _
    Public Shared Function ExecSql(ByVal sql As String) As System.Data.DataTable

        Dim connStr = GlobalSettings.GetConnectionString()
        Using conn As New System.Data.SqlClient.SqlConnection(connStr)
            conn.Open()

            Dim cmd As New System.Data.SqlClient.SqlCommand(sql.ToString, conn)
            Dim adapter As System.Data.SqlClient.SqlDataAdapter = New System.Data.SqlClient.SqlDataAdapter(cmd)
            Dim dt As System.Data.DataTable = New System.Data.DataTable
            adapter.Fill(dt)

            Return dt

            If conn.State <> System.Data.ConnectionState.Closed Then
                conn.Close()
            End If
            conn.Dispose()
        End Using
    End Function
End Class

А вот мой юнит-тест:

Partial Public Class CampaignEmailSendLimitServiceTests
    Inherits TestBase

    Private _service = ServiceManager.Current.MyService

    <TestMethod()> _
    Public Sub MyTest()
        //' Set the pre-test condition.
        ExecSql("update base.dbo.tblTableA set someDate = '2010-06-28' where id = 56937 ")

        //' Run the service
        _service.Process()

       //' Verify the expected result
       Dim dt = ExecSql("select deliveryDate from tblTableB ")
       Assert.AreEqual(False, dt.Rows(0).IsNull("deliveryDate"))

    End Sub
End Class

Ответы [ 3 ]

1 голос
/ 16 мая 2011

Это всегда хорошо для меня. Основное различие, которое я вижу, заключается в использовании TransactionScopeOption.Required.

[TestClass()]
public class MyTest: DatabaseTestClass
{

    public MyTest()
    {
        InitializeComponent();
    }

    TransactionScope ambientTransaction;

    [TestInitialize()]
    public void TestInitialize()
    {
        ambientTransaction = new TransactionScope(TransactionScopeOption.Required);
        base.InitializeTest();
    }

    [TestCleanup()]
    public void TestCleanup()
    {
        ambientTransaction.Dispose();
        base.CleanupTest();
    }
}
0 голосов
/ 17 мая 2011

Я наконец понял, что происходит.Это не имеет ничего общего с транзакциями.Это все работает отлично.Это был мой процесс, который создавал противоречивое поведение - по замыслу.Была часть процесса, которая имела «случайное ранжирование» для определения даты доставки, если не было найдено другого ранжирования.Модульный тест должен быть переписан, чтобы лучше отражать бизнес-правила.

0 голосов
/ 17 мая 2011

Почему Вы используете DataAdapter.Fill для выполнения обновлений? Он предназначен для заполнения DataTables операторами выбора.

Полагаю, вы ничего не записали в базу данных, используя ExecSql.

И второе. Это утверждение настолько нечитаемо, насколько это возможно. Я бы поменял

Assert.AreEqual(False, dt.Rows(0).IsNull("deliveryDate"));

до

Assert.IsFalse(dt.Rows(0).IsNull("deliveryDate"));

или

Assert.That(dt.Rows(0)("deliveryDate"), Is.Not.Null));

Нечитаемые тесты - одна из причин, по которой некоторые люди говорят, что модульное тестирование плохое, потому что замедляет работу. Вы должны сделать модульные тесты как можно более легкими для чтения и понимания. Так что у них нет аргументов против юнит-тестирования;)

Могут быть некоторые опечатки, поскольку я не использую VB.NET. Примеры утверждений взяты из NUnit.

...