1
\$\begingroup\$

I've created unit test for the "student" CRUD operations that looks like this:

[Test]
    public void Can_Exec_CrudOps()
    {
        #region Prepare


        var account = Processor.Execute(new CreateAccount
        {
            Email = "email@example.com",
            Username = "username",
            Password = "password",
        }).Result;

        #endregion

        var student = Processor.Execute(new CreateStudent
        {
            AccountId = account.EntityID
        }).Result;

        Assert.NotNull(student);
        student.AreEqual(Processor.Execute(new GetStudent
        {
            EntityId = student.EntityID
        }).Result);
        student.AreEqual(Processor.Execute(new GetStudentByAccount
        {
            AccountId = account.EntityID
        }).Result);

        var upd_student = Processor.Execute(new UpdateStudent
        {
            EntityId = student.EntityID,
            Flags = StudentFlags.Active
        }).Result;

        Assert.NotNull(upd_student);
        upd_student.AreEqual(student);
        upd_student.Flags.AreEqual(StudentFlags.Active);

        Processor.Execute(new DeleteStudent
        {
            EntityId = student.EntityID
        });
    }

As you can see, the region #prepare contains code that will insert required data to the database for the current test to be possible.

Is it good practice to create a single test for each CRUD operation and then call that test inside the tests that require them?

What I'm thinking about would look like this:

 [TestFixture]
public class StudentTest : OperationTest
{
    protected override IEnumerable<Type> ModelMappings
    {
        get
        {
            return NHMappings.EDUCATION;
        }
    }

    [Test]
    public void Can_Exec_CrudOps()
    {
        #region Prepare
        // here is what changed //
        var acc = new AccountTests();
        var acc_id=    acc.create_account();


        #endregion

        var student = Processor.Execute(new CreateStudent
        {
                        //here too//
            AccountId = acc_id
        }).Result;

        Assert.NotNull(student);
        student.AreEqual(Processor.Execute(new GetStudent
        {
            EntityId = student.EntityID
        }).Result);
        student.AreEqual(Processor.Execute(new GetStudentByAccount
        {
                        // and here//
            AccountId = acc_id
        }).Result);

        var upd_student = Processor.Execute(new UpdateStudent
        {
            EntityId = student.EntityID,
            Flags = StudentFlags.Active
        }).Result;

        Assert.NotNull(upd_student);
        upd_student.AreEqual(student);
        upd_student.Flags.AreEqual(StudentFlags.Active);

        Processor.Execute(new DeleteStudent
        {
            EntityId = student.EntityID
        });
        // and here //
        acc.deleteaccount(acc_id);
    }
}

So the point is not to write the same code over and over again.

\$\endgroup\$
  • 2
    \$\begingroup\$ Please include a language tag next time, since this looks like C#, I added that tag. \$\endgroup\$ – Simon Forsberg Dec 17 '13 at 13:28
5
\$\begingroup\$

No, I would say, and the reason for that is that you have too many asserts in your test (it does to many thinks). There should only be one reason for a test to fail. So:

Split your test into smaller ones with a more descriptive name and stick to one assert per test. By doing so it's also easier to track down why a test is failing, both in the case is the bug is in the test or in the production code.

\$\endgroup\$
  • 1
    \$\begingroup\$ I would also call these integration tests because they are hitting the database. Unit tests are written to test a very specific section of the logic. \$\endgroup\$ – Jeff Vanzella Dec 17 '13 at 20:48

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.