Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.
Comment: Migration of unmigrated content due to installation of a new plugin

...

Test

...

Data

...

Builder

...

One

...

of

...

the

...

more

...

time-consuming

...

and

...

tedious

...

chores

...

in

...

writing

...

unit

...

tests

...

that

...

involve

...

mocks,

...

is

...

setting

...

up

...

the

...

test

...

data

...

for

...

mock

...

expectations.

...

For

...

example,

...

let's

...

say

...

we

...

are

...

testing

...

service

...

class

...

code

...

like

...

this:

{
Code Block
}
List<Student> advisees = advisorDao.getAdvisees();
{code}

Our

...

unit

...

test

...

would

...

use

...

a

...

mock

...

version

...

of

...

advisorDao,

...

and

...

we

...

would

...

tell

...

the

...

mock

...

framework

...

to

...

expect

...

a

...

call

...

to

...

getAdvisees()

...

and

...

for

...

this

...

method

...

call

...

to

...

return

...

a

...

list

...

of

...

Student

...

objects,

...

like

...

so:

{
Code Block
}
expect(advisorDao.getAdvisees()).andReturn(studentList);
{code}

We

...

would

...

need

...

to

...

manually

...

create

...

the

...

studentList

...

list,

...

instantiate

...

a

...

number

...

of

...

Student

...

objects,

...

and

...

add

...

them

...

all

...

to

...

the

...

list.

...

Perhaps

...

our

...

test

...

also

...

requires

...

us

...

to

...

peek

...

inside

...

the

...

Student

...

objects

...

and

...

examine

...

the

...

enrollment

...

profile

...

or

...

other

...

embedded

...

objects.

...

We

...

would

...

be

...

required

...

to

...

instantiate

...

all

...

of

...

these

...

objects

...

and

...

set

...

them

...

inside

...

our

...

Student

...

objects.

...

This

...

takes

...

a

...

lot

...

of

...

time

...

and

...

is

...

very

...

tedious.

...

The

...

intent

...

of

...

the

...

test

...

data

...

builder

...

framework

...

is

...

to

...

make

...

"helper"

...

classes

...

available

...

that

...

will

...

do

...

a

...

lot

...

of

...

this

...

data

...

setup

...

for

...

the

...

programmer.

...

These

...

will

...

be

...

simple

...

factory

...

classes,

...

instantiating

...

commonly

...

used

...

objects

...

like

...

Student,

...

and

...

populating

...

them

...

with

...

values

...

that

...

make

...

sense.

...

Design

...

considerations:

...

  • Make

...

  • the

...

  • framework

...

  • simple

...

  • and

...

  • easy

...

  • to

...

  • use

...

  • Keep

...

  • the

...

  • interfaces

...

  • uncluttered

...

  • Provide

...

  • the

...

  • basics

...

  • that

...

  • should

...

  • be

...

  • good

...

  • enough

...

  • for

...

  • most

...

  • tests,

...

  • but

...

  • allow

...

  • the

...

  • flexibility

...

  • for

...

  • unit

...

  • tests

...

  • to

...

  • tweak

...

  • the

...

  • data

...

  • if

...

  • necessary.

...

Here

...

is

...

an

...

example

...

of

...

one

...

of

...

these

...

builder

...

classes

...

-

...

it's

...

called

...

CoreDataFactory

...

and

...

is

...

intended

...

to

...

provide

...

common

...

data

...

used

...

across

...

many

...

apps.

...

The

...

interfaces

...

for

...

creating

...

Student

...

objects

...

is

...

like

...

this:

{
Code Block
}
public Student buildStudent();

public Student buildStudent(String termCode);
{code}

There

...

are

...

just

...

two

...

variations

...

-

...

the

...

first

...

(no-arg)

...

method

...

will

...

return

...

a

...

Student

...

object

...

with

...

all

...

basic

...

data

...

fields

...

filled

...

in.

...

It

...

will

...

also

...

populate

...

enrollment

...

profile

...

information

...

for

...

the

...

current

...

term

...

(based

...

on

...

a

...

simple

...

current

...

date

...

calculation).

...

The

...

second

...

method,

...

taking

...

term

...

code

...

as

...

an

...

argument

...

builds

...

a

...

similar

...

Student

...

object,

...

but

...

it

...

uses

...

the

...

supplied

...

term

...

code

...

for

...

any

...

term-specific

...

data

...

like

...

enrollment

...

profile.

...

The

...

builder

...

methods

...

will

...

randomly

...

generate

...

values

...

for

...

the

...

student

...

name,

...

mit

...

id,

...

pidm,

...

kerb

...

name,

...

etc,

...

so

...

that

...

each

...

student

...

object

...

returned

...

by

...

the

...

builder

...

methods

...

will

...

be

...

different.

...

So

...

a

...

unit

...

test

...

needing

...

Student

...

objects

...

for

...

test

...

data

...

now

...

only

...

needs

...

to

...

do

...

this

...

for

...

each

...

student

...

object:

{
Code Block
}
Student student = builder.buildStudent();
{code}

and no longer needs to do this:

Code Block


and no longer needs to do this:

{code}
PersonName personName = new PersonName("David", "Lee", "Roth");
String kerbName = "dlr";
String emailAddress = kerbName + "@mit.edu";

int pidm = 12212871;
int mitId = 90002312;

Student student = new Student(String.valueOf(pidm), String.valueOf(mitId), kerbName,
                              personName, emailAddress);
Calendar now = Calendar.getInstance();

student.setCitizenship(new Citizenship("US", "United States"));
student.setEthnicity(new StudentEthnicity());
Calendar birthDate = Calendar.getInstance();
birthDate.set(Calendar.YEAR, birthDate.get(Calendar.YEAR) - 20);  // Born 20 years ago
student.setBirthDate(birthDate.getTime());
student.setDeceased(false);
student.setGender(Gender.FEMALE);
student.setStudentHolds(new ArrayList<StudentHold>());
student.setVersion(1l);
student.setCreateBy("testuser");
student.setCreateDate(now.getTime());
student.setModifyBy("testuser2");
student.setModifyDate(now.getTime());

 // Enrollment profile:
Set enrollProfiles = new HashSet();

// ... more code that builds enrollment profile objects...

student.setStudentEnrollProfiles(enrollProfiles);

{code}

h3. Test Builder Package / Module Location

I originally thought that the test builder factory classes would go into the csf-test module, as they are intended to be helper classes for unit tests. However, because the builder classes use the domain classes, this setup would cause circular dependencies - for example, 

Test Builder Package / Module Location

I originally thought that the test builder factory classes would go into the csf-test module, as they are intended to be helper classes for unit tests. However, because the builder classes use the domain classes, this setup would cause circular dependencies - for example, csf-common-legacy

...

would

...

depend

...

on

...

csf-test,

...

and

...

csf-test

...

would

...

depend

...

on

...

csf-common-legacy.

...

Because

...

of

...

this,

...

it

...

seems

...

to

...

make

...

sense

...

to

...

place

...

the

...

builder

...

classes

...

close

...

to

...

the

...

domain

...

objects

...

they

...

are

...

building.

...

So

...

the

...

CoreDataFactory

...

could

...

go

...

into

...

csf-common-legacy

...

in

...

a

...

new

...

package

...

in

...

the

...

domain

...

area:

...

edu.mit.common.domain.builders

...

A

...

different

...

way

...

of

...

looking

...

at

...

this

...

is

...

that

...

by

...

creating

...

the

...

helper

...

classes,

...

we

...

are

...

just

...

abstracting

...

out

...

duplicate

...

code

...

from

...

the

...

unit

...

test

...

classes

...

themselves.

...

So

...

perhaps

...

the

...

builders

...

do

...

belong

...

in

...

the

...

test

...

hierarchy.

...

They

...

are

...

not

...

strictly

...

unit

...

tests

...

themselves,

...

but

...

by

...

putting

...

them

...

under

...

test,

...

they

...

would

...

only

...

be

...

used

...

when

...

tests

...

were

...

run

...

and

...

would

...

not

...

be

...

deployed

...

as

...

part

...

of

...

an

...

app.

...

Core

...

Data

...

Factory

...

Javadoc

...

Here's

...

a

...

screenshot

...

showing

...

the

...

Javadoc

...

for

...

the

...

Core

...

Data

...

Factory

...

class.

Image Added

Does the Core Data Factory Satisfy the Goals?

Here's how I think the factory prototype satisfies the goals:

  • Make the framework simple and easy to use

Once you have an instance of CoreDataFactory, getting a stucb Student object is a single method call.

  • Keep the interfaces uncluttered

Taking student as an example, there are two build options: one that takes no arguments, one that takes a single termCode argument. We could have created a longer arg list for finer grained customization, but it seems better to keep the interface short and simple. If a unit test needs to tweak the data, it can do that after getting the student object.

  • Provide the basics that should be good enough for most tests, but allow the flexibility for unit tests to tweak the data if necessary.