Friday, August 10

CRUD unit-testing checklist

I'm writing a unit-test code generator for CRUD operations to keep me from repeating myself. In preparation for this, I'm compiling a comprehensive set of CRUD unit-tests beyond the eponymous ones.

So, for a given business object Foo I may want to test:

Create


public void TestCreate_NullFoo {
try {
PersistenceServices.create(Null);
} catch(PersistenceServiceException pse){
return;
}
fail("Expected exception not thrown");
}

// possible test, depends on requirements
public void TestCreate_EmptyFoo {
Foo foo = new Foo(); // no properties set
try {
PersistenceServices.create(foo);
} catch(PersistenceServiceException pse){
return;
}
fail("Expected exception not thrown");
}

// depends on requirements; validation shouldn't happen here
public void TestCreate_InvalidFoo {
Foo foo = new Foo();
foo.set...; // populate with known invalid values
try {
PersistenceServices.create(foo);
} catch(PersistenceServiceException pse){
return;
}
fail("Expected exception not thrown");
}

// depends on requirements; validation shouldn't happen here
public void TestCreate_IncompleteFoo {
Foo foo = new Foo();
foo.set...; // miss required values
try {
PersistenceServices.create(foo);
} catch(PersistenceServiceException pse){
return;
}
fail("Expected exception not thrown");
}

public void TestCreate_IncrementsCount {
int beforeCreate = PersistenceServices.countFoos();
Foo foo = new Foo();
foo.set...; // populate with required values
PersistenceServices.create(foo);
int afterCreate = PersistenceServices.countFoos();
assertTrue(afterCreate > beforeCreate);
}

public void TestCreate_IsNotIdempotent {
Foo foo = new Foo();
foo.set...; // populate with required values
Foo aCreated = PersistenceServices.create(foo);
Foo bCreated = PersistenceServices.create(foo);
assertNotEquals(aCreated, bCreated);
}

public void TestCreate_Foo {
Foo foo = new Foo();
foo.set...; // populate with required & validated values
Foo created = PersistenceServices.create(foo);
assertEquals(foo, created);
}



Read

public void TestRead_NullFoo {
Foo read = PersistenceServices.getFoo(Null);
assertNull(read);
}

// depends on requirements
public void TestRead_EmptyFooId {
Foo read = PersistenceServices.getFoo("");
assertNull(read);
}

public void TestRead_DoesNotIncrementCount {
int beforeRead = PersistenceServices.countFoos();
PersistenceServices.getFoo(aFoo); // aFoo is known, existing Foo
int afterRead = PersistenceServices.countFoos();
assertTrue(beforeRead == afterRead);
}

public void TestRead_DuplicateFoo { // see IsIdempotent below
}

public void TestRead_IsIdempotent {
Foo aFoo = PersistenceServices.getFoo(aFoo);
Foo bFoo = PersistenceServices.getFoo(aFoo);
assertEquals(aRead, bRead);
}

// depends on requirements; could throw friendly exception
public void TestRead_DeletedFoo {
Foo deleted = PersistenceServices.delete(aFoo);
Foo read = PersistenceServices.getFoo(deleted);
assertNull(read);
}

public void TestRead_FooById {
Foo foo = new Foo();
foo.set...; // populate with required & validated values
Foo created = PersistenceServices.create(foo);
Foo read = PersistenceServices.getById(created.id);
assertEquals(foo, read);
}



Update

public void TestUpdate_NullFoo {}

public void TestUpdate_EmptyFoo {}

public void TestUpdate_InvalidFoo {}

public void TestUpdate_IncompleteFoo {}

public void TestUpdate_DuplicateFoo {}

public void TestUpdate_UnchangedFoo {}

public void TestUpdate_DoesNotIncrementCount {}

public void TestUpdate_IsIdempotent {}

public void TestUpdate_UndoFoo {}

public void TestUpdate_Foo {}



Delete

public void TestDelete_NullFoo {
Foo deleted = PersistenceServices.delete(Null);
assertNull(deleted);
}

public void TestDelete_EmptyFoo { // dependent of business requirements
Foo foo = new Foo(); // no properties set
Foo deleted = PersistenceServices.delete(foo);
assertNull(deleted);
}

public void TestDelete_InvalidFoo {
}

public void TestDelete_IncompleteFoo {
}

public void TestDelete_DuplicateFoo {
}

public void TestDelete_DecrementsCount {
Foo aFoo = PersistenceServices.getFoo(aFoo);
int beforeDelete = PersistenceServices.countFoos();
PersistenceServices.delete(aFoo);
int afterDelete = PersistenceServices.countFoos();
assertTrue(beforeDelete > afterDelete);
}

public void TestDelete_IsIdempotent {
Foo aFoo = PersistenceServices.delete(aFoo);
Foo bFoo = PersistenceServices.getFoo(aFoo);
assertNull(bFoo);
aFoo = PersistenceServices.delete(aFoo);
bFoo = PersistenceServices.getFoo(aFoo);
assertNull(bFoo);
}

public void TestDelete_ExistingFoo {
Foo aFoo = PersistenceServices.delete(aFoo);
assertNotNull(aFoo);
Foo bFoo = PersistenceServices.getFoo(aFoo);
assertNull(bFoo);
}

public void TestDelete_MissingFoo {
// aFoo does not exist
Foo deleted = PersistenceServices.delete(aFoo);
assertNull(deleted); // could expect exception
}

// depends on requirements
public void TestDelete_ReturnsDeleted {
Foo aFoo = PersistenceServices.getById(aFoo.id);
Foo deleted = PersistenceServices.delete(aFoo);
assertEquals(aFoo, deleted);
}


(Vaguely) Related Posts
Testing For Developers
Automated Unit Testing
CRUD base classes for unit testing
Unitils Guidelines

No comments: