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 protected]",
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.
-
2\$\begingroup\$ Please include a language tag next time, since this looks like C#, I added that tag. \$\endgroup\$Simon Forsberg– Simon Forsberg2013年12月17日 13:28:31 +00:00Commented Dec 17, 2013 at 13:28
1 Answer 1
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.
-
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– Jeff Vanzella2013年12月17日 20:48:19 +00:00Commented Dec 17, 2013 at 20:48