I have written some code in Katalon Studio (known as "custom keywords") whose job is to map the rows of a Data File to models for testing. Say goodbye to hardcoded column indices and findTestData("YourDataStoreName") all over test case code!
It is defined to be:
package com.xxx.builders // imports public abstract class BaseModelBuilder<T> { protected TestData testData; public BaseModelBuilder(TestData testData) { this.testData = testData; } public List<T> createModels() { return this.testData.getAllData() .stream() .filter { row -> row.stream().anyMatch { String cell -> cell != null && !cell.isEmpty() } } .map { row -> this.createModelFromRow(row) } .collect(Collectors.toList()) } public T createModelFromRowNum(int rowNum) { return this.createModelFromRow(this.testData.getAllData().get(rowNum)) } public abstract T createModelFromRow(List<Object> row) } and when we want to use it, we extend it, for example :
package com.xxx.builders // imports public class ContractBuilder extends BaseModelBuilder<ContractModel> { public ContractBuilder() { super(findTestData('PracticeContractData')) } public ContractModel createModelFromContractID(int contractID) { int contractIdx = this.findContractIndex(contractID) return this.createModelFromRowNum(contractIdx) } private int findContractIndex(int contractForeignKey) { for (int $j = 1; $j <= this.testData.getRowNumbers(); $j++) { if (Integer.parseInt(this.testData.getValue(1, $j)) == contractForeignKey) { return $j } } return -1 } @Override public ContractModel createModelFromRow(List<Object> row) { return new ContractModel( Integer.parseInt(row[0]), Formats.DateFormat.parse(row[2]), Formats.DateFormat.parse(row[3]), Integer.parseInt(row[4]), row[6], Double.parseDouble(row[5]), Frequency.valueOfText(row[7]), Integer.parseInt(row[8]), Integer.parseInt(row[10]), (row[11] == 'Y'), Integer.parseInt(row[12]), row[13], Signatory.valueOfText(row[14]), new BankDetailModel(Double.valueOf(row[15]), Double.valueOf(row[16]), Double.valueOf(row[17])), Double.valueOf(row[18]), ) } } And then call it, typically in enhanced for-loop, like for (YourModel model : new YourBuilder().createModels()) { /* test code */}
The problem is that I don't know what to call this solution. I'm probably wrong about this, but it doesn't seem to fit neatly into factory design pattern, and doesn't have the static inner-class status and field-matching that a proper builder does.
What is the correct name for this design pattern?
DISCLAIMER: Katalon Studio's runtime environment is in Groovylang, which is a dialect of Java.