I propose here a simple approach for testing your generator written using oAW and the JUnit test framework. A generator usually consists of model to model transformations and model to code transformations. It would be nice if one could test these steps independently, without having to run the whole generator (or workflow in oAW terms).
Let's consider this simple example: convert from an object model (a class) to a relational model (a table) and finally create text (SQL statements).
For the first transformation (M2M, from class to table), we have an Xtend extension (in the file obj2rel.ext). Please note that the code has been simplified in the next listings for readability.
Table transformClass( Class c ): setName( c.name ) -> getColumns().add( c.attributes.transformAttribute() ) ;
For the second one (M2T, from Table to text), we have an XPand template (in the file rel2sql.xpt):
«DEFINE sql for Table» create table «name» ( «EXPAND sql for columns » ) «ENDDEFINE»
First of all I would like to test if the table created after the M2M transformation is right. For that, I define a unit test:
public class TestTable { private XtendCaller ext; @Before public void init(){ ext = new XtendCaller("my::package::obj2rel", "metamodelPackage_Object", "metamodelPackage_Relational"); } @Test public void testObj2Rel(){ Class c = createTestClass("TestClass", "att1", "String", "att2", "Integer"); Table t = (Table)ext.call("transformClass", c ); assertEquals( c.getName(), t.getName() ); assertEquals( c.getAttributes().size(), t.getColumns().size() ); // more asserts ... } }
Then, as I did it for my extensions, I test the model to text transformation by defining another unit test:
public class TestSql { private XpandCaller xpt; @Before public void init(){ xpt = new XpandCaller("metamodelPackage_Relational"); } @Test public void testObj2Rel(){ Table t = createTestTable("..."); xpt.evaluate("my::package::rel2sql", pl1dt); String expexted = IOUtils.toString( new FileInputStream(new File("reference.file")) ); assertEquals(expected, xpand.getOutput() ); } }
As you can see, the various unit tests can cover different parts of the transformation independently. You can also combine a model to model transformation and a model to text transformation in one test if you do not want to use intermediate test data. The real advantage comes by leveraging the JUnit framework in an IDE like Eclipse where you can simply use the diff feature to see where a test fails. This is extremely helpful for comparing string objects such as a text file (which contains the reference artefact) and the result of a M2T template transformation (see next figure).
The two helper classes XtendCaller and XpandCaller are helpful decorators over the two classes XtendFacade resp. XpandFacade already available within the oAW framework. You will the code for these classes here:
XtendCaller
XpandCaller
StringOutput
Thanks to Antoine Logean for his feedback on this approach.