Prueba de unidad resultado inconsistente de aprobado o reprobado

Una de mis pruebas unitarias parece pasar o fallar aleatoriamente cuando la ejecuto. Lo único que tiene sentido para mí de por qué sucede esto es si los datos en la base de datos entran en un estado diferente cada vez que se ejecuta la prueba, pero uso transacciones para revertir la base de datos en cada prueba, a menos que no esté funcionando correctamente. . Aquí está mi clase de prueba de unidad base y la clase de prueba de unidad que tiene el problema. ¿Puedes ver algo que pueda estar perdiendo o qué más debo buscar?

Esto sucede con TestDriven.Net y el marco de pruebas unitarias de 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

Y aquí está mi prueba unitaria:

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

preguntado el 16 de mayo de 11 a las 18:05

¿Está ejecutando un conjunto completo de pruebas o solo esta prueba una y otra vez? Es posible que desee ejecutar esta prueba una y otra vez para ver si sigue siendo inconsistente. Si funciona bien cuando se ejecuta por sí solo, es posible que tenga otra prueba que no esté limpiando el estado de la base de datos de manera adecuada. -

No, solo estoy haciendo esta prueba una y otra vez. -

3 Respuestas

Esto siempre me ha funcionado bien. La principal diferencia que veo es el uso de 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();
    }
}

contestado el 16 de mayo de 11 a las 23:05

Desafortunadamente, todavía sucede si lo cambio a Requerido. - adam0101

¿Por qué está utilizando DataAdapter.Fill para ejecutar actualizaciones? Está diseñado para llenar DataTables con declaraciones de selección.

Supongo que no escribió nada en la base de datos usando ExecSql en primer lugar.

Y lo segundo. Esa afirmación es lo más ilegible posible. me gustaría cambiar

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

a

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

or

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

Las pruebas ilegibles son una de las razones por las que algunas personas dicen que las pruebas unitarias son malas porque lo ralentizan. Debe hacer que las pruebas unitarias sean lo más fáciles de leer y comprender posible. Para que no tengan argumentos en contra de las pruebas unitarias;)

Puede haber algunos errores tipográficos ya que no uso VB.NET. Los ejemplos de afirmación son de NUnit.

contestado el 17 de mayo de 11 a las 01:05

Gracias por los consejos de formato, pero esto realmente no responde a mi pregunta. - adam0101

Dar formato a los comentarios fue una ventaja. Dije lo que creo que estás haciendo mal. Pero no escuchas. DataAdapter.Fill NO es para enviar datos a la base de datos. ¿Y cómo espera buenas respuestas si no muestra lo que hay en el proceso? Creo que el voto negativo es muy grosero aquí. - Piotr Perak

Finalmente me di cuenta de lo que estaba pasando. No tuvo nada que ver con transacciones. Todo eso está funcionando muy bien. Era mi proceso el que estaba creando un comportamiento inconsistente, por diseño. Había una parte del proceso que tenía una "clasificación aleatoria" para determinar la fecha de entrega si no se encontraban otras clasificaciones. La prueba unitaria debe reescribirse para reflejar mejor las reglas comerciales.

contestado el 17 de mayo de 11 a las 20:05

No es la respuesta que estás buscando? Examinar otras preguntas etiquetadas or haz tu propia pregunta.