Question

Un de mes tests unitaires semble passer au hasard ou échouer lorsque je l'exécute. La seule chose qui a du sens pour moi de savoir pourquoi cela se produit, c'est si les données de la base de données entrent dans un état différent chaque fois que le test est effectué, mais j'utilise des transactions pour faire reculer la base de données dans chaque test - sauf si cela ne fonctionne pas correctement . Voici ma classe de test d'unité de base et la classe de test unitaire qui a le problème. Pouvez-vous voir quelque chose qui pourrait manquer ou ce que je devrais rechercher d'autre?

Cela se produit avec TestDriven.net et Le cadre de test d'unité 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

Et voici mon test unitaire:

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
Était-ce utile?

La solution 3

J'ai finalement compris ce qui se passait. Cela n'avait rien à voir avec les transactions. Tout cela fonctionne très bien. C'était mon processus qui créait un comportement incohérent - par conception. Il y a eu une partie du processus qui avait un "classement aléatoire" pour déterminer la livraison de la livraison si aucun autre classement n'est trouvé. Le test unitaire doit être réécrit pour mieux refléter les règles commerciales.

Autres conseils

Cela a toujours fonctionné pour bien pour moi. La principale différence que je vois est d'utiliser 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();
    }
}

Pourquoi utilisez-vous dataadapter.fill pour exécuter des mises à jour? Il est conçu pour remplir les données de données avec des instructions sélectionnées.

Je suppose que vous n'avez rien écrit dans la base de données en utilisant EXECSQL en premier lieu.

Et la deuxième chose. Cette affirmation est aussi illisible que possible. je voudrais changer

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

à

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

ou

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

Les tests illisibles sont l'une des raisons pour lesquelles certaines personnes disent que les tests unitaires sont mauvais car cela vous ralentit. Vous devez rendre les tests unitaires aussi faciles à lire et à comprendre que possible. Pour qu'ils n'aient pas d'arguments contre les tests unitaires;)

Il peut y avoir des fautes de frappe car je n'utilise pas VB.NET. Les exemples d'affirmation sont de Nunit.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top