Skip to content

Specifying test data

With RedG you specify all your test data in pure Java code. And "all your test data" means "only the data you really need". RedG takes care of all the other stuff (like not specified NOT NULL fields, required foreign key relations etc.).

General API design

The entity classes RedG generates use a fluent interface with getters and setters in "JQuery style" (no get/set prefix, calling without parameter gets the value, with parameter sets it).

RedG always generates a "main class" (or "manager class"). This is not an executable class containing a public static void main(String[] args), but the class you'll use to create and manage your RedG entities (and thus your test data). This class is usually named RedG.

Using the RedG main class you can create entities. An entity is a java object that represents one row of data that will be inserted into a database (or already exists in the database). Usually you can use methods to change fields ("columns" in your database) on these entities.

Adding an entity

To create a new entity and add it to RedG's internal list of objects to insert call one of the add...() methods on a RedG object. Replace ... with the name of the entity you want to add. If the entity has required fields (either NOT NULL foreign keys or columns / foreign keys marked as explicit) you'll need to pass them to the method. Passing a null value will result in a NullPointerException.

Once you have created your entity you can use it's setters to set the values for the necessary fields.

Example:

RedG redG = new RedG();
// or when customizing many internal things, consider using the RedGBuilder class
// RedG redG = new RedGBuilder<RedG>().build();

// either 
GTeacher mathTeacher = redG.addTeacher()
    .name("Leonhard Euler")
    .age(310);

// or just
redG.addTeacher()
    .name("Isaac Newton");

// or even
GTeacher chemistryTeacher = redG.addTeacher();
chemistryTeacher
    .name("Niels Bohr")
    .hasNobelPrice(true)

When you do not need an entity for further foreign key relations or data manipulation, there is no need to save it in a variable.

As you can see in the example, different fields are set for mathTeacher and chemistryTeacher although they are of the same type and have the same columns. Even if age or hasNobelPrice would both be mandatory (NOT NULL) this code would still work, as RedG generates default values for all fields that are not specified by the user.

Example for entities with NOT NULL foreign key or explicit attributes:

// name of school is an explicit attribute for demonstration purposes
redG.addSchool("Time-traveling School with famous teachers")
    .headmaster(einstein);

// Every class needs a teacher, so it is specified at creation time and may not be null
GClass chemistryClass = redG.addClass(chemistryTeacher)
    .name("Chemistry 101")
    .maxStudentCount(45)

Generating a dummy entity

There are many scenarios where you need to test a specific entity but only need some or none of its dependencies. With most other tools you would have to specify each and every dependency (and their dependencies and so on) and you could wind up with far too much code/XML for just one entity.

To solve this problem RedG offers a dummy entity generator, that will generate a valid dummy entity for you. This entity will have meaningless values but is still a valid entity that can be referenced wherever you want.

To stay in the educational environment with this example, imagine a test case where you need to test the SCHOOL_SUBJECT table (SchoolSubject entity name, GSchoolSubject entity class name). Every subjects needs a teacher. A teacher is a human with a pay grade, a qualification and a school he graduated from (All of these have to be provided because of constraints on the database). Every subjects needs one required textbook as well.

// Without dummy entities and without the previously defined entities

GSchool school = redG.addSchool("Wherever Primary School");
GHuman somePerson = redG.addHuman();
GTeacher someTeacher = redG.addTeacher(somePerson, Paygrade.TEACHER, 
    Qualifications.NONE, school);
GTextBook textBook = redG.addTextBook();

GSchoolSubject aqm = redg.addSchoolSubject(someTeacher, textBook)
    .name("Advanced quantum mechanics")
    .isCoreClass(true)
    .room("1.42");

// with RedGs dummy generator

GSchoolSubject aqm = redG.addSchoolSubject(
        redG.dummyTeacher(),
        redG.dummyTextBook()
)
    .name("Advanced quantum mechanics")
    .isCoreClass(true)
    .room("1.42");

Referencing existing entities

Depending on your setup you might already have some data in your database before running RedG and need to reference these data for a foreign key relation within RedG.

RedG allows you to specify that a certain entity is already present in the database. When inserting you test data RedG will test that the specified entity is really already in the database.

To reference an existing entity, use the existing...() methods of the RedG object. You have to pass the full primary key as the arguments to these methods. If a table does not have primary keys, you cannot reference it.

Example:

GTeacher euklid = redG.existingTeacher(4); // 4 is value of primary id column

// use euklid just like normal for references, just don't try to modify him or read values other the primary keys

// trying to modify fields will throw an UnsupportedOperationException
euklid.isDead(false); 

redG.addMemorialDay(euklid) // works just like expected

Self-references / Circular dependencies

RedG supports self-references via the RedG#entitySelfReference() method. If you have a schema like

create table TREE_ELEMENT (
  ID number(19) not null primary key,
  VALUE varchar2(50 char),
  PARENT_ID number(19) not null,

  constraint FK_TREE_ELEMENT_PARENT foreign key (PARENT_ID) REFERENCES TREE_ELEMENT(ID)
);

you can simply create a root element referencing itself as the parent with redg.addTreeElement(redg.entitySelfReference()).value("Root").

Other circular references and dependencies are currently not supported by RedG. If you really do need this, the best way would be to break open the circle in one place in the specified test data and then "close" the circle with a manual INSERT after you inserted the test data.