A modular way to do data-driven testing

Intro

Anyone here probably already knows about data-driven test cases.

You create some Excel file…

You link it in your Katalon Studio IDE as a Data File…

You reference that Data File, either in the test case code itself, or the test case data binding…

Chance are, you’re like how I was in September 2021, when I started my freelancing job doing this, and inherit a code base where the former design decision was made, and the test cases look like this:

Real life horror story // Don’t let this happen to you !

for ($i = 1; $i <= findTestData('NewZohoData').getRowNumbers(); $i++) {
    WebUI.navigateToUrl(findTestData('NewZohoData').getValue(11, $i))
    
    WebUI.scrollToElement(findTestObject('Page_Red Group Practice (Practice) - Zoho CRM/div_PersonnelOffice DetailsMember LeadMember DetailsExpensesEarnout DetailBuyout Details'), 
        0)
        
    WebUI.delay(5)
    
    WebUI.click(findTestObject('Page_DeLink Test Practice (Practice) - Zoho CRM/span_Member Lead'))
    
    WebUI.click(findTestObject('Page_Red Group Practice (Practice) - Zoho CRM/lyte-yield_New Member Lead'))
    
    WebUI.setText(findTestObject('Page_Create Member Lead - Zoho CRM/textarea_DescriptionNotes_Crm_Potentials_POTENTIALCF125'), 
        'This is a description of the Member Lead')
        
    WebUI.setText(findTestObject('Page_Create Member Lead - Zoho CRM/input_First Name_Crm_Potentials_POTENTIALCF21'), findTestData(
            'NewZohoData').getValue(1, $i))

    WebUI.setText(findTestObject('Page_Create Member Lead - Zoho CRM/input_Last Name_Crm_Potentials_POTENTIALCF20'), findTestData(
            'NewZohoData').getValue(2, $i))

    WebUI.setText(findTestObject('Page_Create Member Lead - Zoho CRM/input_Email_Crm_Potentials_POTENTIALCF14'), findTestData(
            'NewZohoData').getValue(9, $i))

    WebUI.setText(findTestObject('Page_Create Member Lead - Zoho CRM/input_Home Phone Number_Crm_Potentials_POTENTIALCF18'), 
        findTestData('NewZohoData').getValue(3, $i))

    WebUI.setText(findTestObject('Page_Create Member Lead - Zoho CRM/input_Date of Birth_Crm_Potentials_POTENTIALCF81'), 
        findTestData('NewZohoData').getValue(17, $i))

    WebUI.scrollToElement(findTestObject('Page_Create Member Lead - Zoho CRM/td_Member Lead Information'), 0)

    WebUI.click(findTestObject('Page_Create Member Lead - Zoho CRM/input_Organization_Crm_Potentials_POTENTIALCF114'))

    WebUI.click(findTestObject('Page_Create Member Lead - Zoho CRM/span_SMD-BETA'))

    //Pick initial Type
    if (findTestData('NewZohoData').getValue(13, $i) == 'I') {
        WebUI.click(findTestObject('Page_Create Member Lead - Zoho CRM/span_Individual'))

        WebUI.clickOffset(findTestObject('Page_Create Member Lead - Zoho CRM/span_Individual'), -150, 70)

    } else if (findTestData('NewZohoData').getValue(13, $i) == 'C') {
        WebUI.click(findTestObject('Page_Create Member Lead - Zoho CRM/span_Individual'))

        WebUI.clickOffset(findTestObject('Page_Create Member Lead - Zoho CRM/span_Individual'), -150, 100)

    } else {
        WebUI.click(findTestObject('Page_Create Member Lead - Zoho CRM/span_Individual'))

        WebUI.clickOffset(findTestObject('Page_Create Member Lead - Zoho CRM/span_Individual'), -150, 130)

    }
    
    //Need to do the same for Member Type somehow....
    if (findTestData('NewZohoData').getValue(14, $i) == 'I') {
        WebUI.click(findTestObject('Page_Create Member Lead - Zoho CRM/span_Individual (1)'))

        WebUI.clickOffset(findTestObject('Page_Create Member Lead - Zoho CRM/span_Individual (1)'), 0, 68)

    } else {
        WebUI.click(findTestObject('Page_Create Member Lead - Zoho CRM/span_Individual (1)'))

        WebUI.clickOffset(findTestObject('Page_Create Member Lead - Zoho CRM/span_Individual (1)'), 0, 98)

        WebUI.setText(findTestObject('Page_Create Member Lead - Zoho CRM/input_Related Family Member_Crm_Potentials_POTENTIALCF01'), 
            findTestData('NewZohoData').getValue(15, $i))

        WebUI.delay(3)

        WebUI.clickOffset(findTestObject('Page_Create Member Lead - Zoho CRM/input_Related Family Member_Crm_Potentials_POTENTIALCF01'), 
            0, 55)

    }
    
    WebUI.setText(findTestObject('Page_Create Member Lead - Zoho CRM/input_Lead Date_Crm_Potentials_POTENTIALCF82'), findTestData(
            'NewZohoData').getValue(18, $i))

    if (findTestData('NewZohoData').getValue(19, $i) == 'Y') {
        WebUI.click(findTestObject('Page_Create Member Lead - Zoho CRM/input_Back Date_Crm_Potentials_POTENTIALCF108'))

        WebUI.setText(findTestObject('Page_Create Member Lead - Zoho CRM/input_Tentative Contract Start Date_Crm_Potentials_POTENTIALCF84'), 
            findTestData('NewZohoData').getValue(20, $i))

    } else {
    }
    
    if (findTestData('NewZohoData').getValue(12, $i) == 'Membership') {
        WebUI.click(findTestObject('Page_Create Member Lead - Zoho CRM/input_Member Category_Crm_Potentials_POTENTIALCF04'))

        WebUI.click(findTestObject('Page_Create Member Lead - Zoho CRM/span_Membership'))

    } else if (findTestData('NewZohoData').getValue(12, $i) == 'Pediatric') {
        WebUI.click(findTestObject('Page_Create Member Lead - Zoho CRM/input_Member Category_Crm_Potentials_POTENTIALCF04'))

        WebUI.clickOffset(findTestObject('Page_Create Member Lead - Zoho CRM/input_Member Category_Crm_Potentials_POTENTIALCF04'), 
            0, 40)

    } else if (findTestData('NewZohoData').getValue(12, $i) == 'Standard') {
        WebUI.click(findTestObject('Page_Create Member Lead - Zoho CRM/input_Member Category_Crm_Potentials_POTENTIALCF04'))

        WebUI.click(findTestObject('Page_Create Member Lead - Zoho CRM/span_Standard Membership'))

    } else if (findTestData('NewZohoData').getValue(12, $i) == 'Silver') {
        WebUI.click(findTestObject('Page_Create Member Lead - Zoho CRM/input_Member Category_Crm_Potentials_POTENTIALCF04'))

        WebUI.click(findTestObject('Page_Create Member Lead - Zoho CRM/span_Silver Membership'))

    } else if (findTestData('NewZohoData').getValue(12, $i) == 'Gold') {
        WebUI.click(findTestObject('Page_Create Member Lead - Zoho CRM/input_Member Category_Crm_Potentials_POTENTIALCF04'))

        WebUI.click(findTestObject('Page_Create Member Lead - Zoho CRM/span_Gold Membership'))

    }
    
    if (findTestData('NewZohoData').getValue(16, $i) == 'S') {
        WebUI.click(findTestObject('Page_Create Member Lead - Zoho CRM/span_Annual'))

        WebUI.clickOffset(findTestObject('Page_Create Member Lead - Zoho CRM/span_Annual'), -100, 100)

    } else if (findTestData('NewZohoData').getValue(16, $i) == 'Q') {
        WebUI.click(findTestObject('Page_Create Member Lead - Zoho CRM/span_Annual'))

        WebUI.clickOffset(findTestObject('Page_Create Member Lead - Zoho CRM/span_Annual'), -100, 135)

    } else if (findTestData('NewZohoData').getValue(16, $i) == 'M') {
        WebUI.click(findTestObject('Page_Create Member Lead - Zoho CRM/span_Annual'))

        WebUI.clickOffset(findTestObject('Page_Create Member Lead - Zoho CRM/span_Annual'), -100, 170)

    }
    
    if (findTestData('NewZohoData').getValue(21, $i) == 'Check') {
        WebUI.click(findTestObject('Page_Create Member Lead - Zoho CRM/span_-None-'))

        WebUI.clickOffset(findTestObject('Page_Create Member Lead - Zoho CRM/span_-None-'), -100, 65)

    } else if (findTestData('NewZohoData').getValue(21, $i) == 'ACH') {
        WebUI.click(findTestObject('Page_Create Member Lead - Zoho CRM/span_-None-'))

        WebUI.clickOffset(findTestObject('Page_Create Member Lead - Zoho CRM/span_-None-'), -100, 95)

    } else if (findTestData('NewZohoData').getValue(21, $i) == 'Credit Card') {
        WebUI.click(findTestObject('Page_Create Member Lead - Zoho CRM/span_-None-'))

        WebUI.clickOffset(findTestObject('Page_Create Member Lead - Zoho CRM/span_-None-'), -100, 125)

    }
    
    //Scroll to Address
    WebUI.scrollToElement(findTestObject('Page_Create Member Lead - Zoho CRM/td_Address Information'), 0)

    WebUI.setText(findTestObject('Page_Create Member Lead - Zoho CRM/input_Address Line 1_Crm_Potentials_POTENTIALCF7'), 
        findTestData('NewZohoData').getValue(4, $i))

    WebUI.setText(findTestObject('Page_Create Member Lead - Zoho CRM/input_Address Line 2_Crm_Potentials_POTENTIALCF8'), 
        findTestData('NewZohoData').getValue(5, $i))

    WebUI.setText(findTestObject('Page_Create Member Lead - Zoho CRM/input_City_Crm_Potentials_POTENTIALCF2'), findTestData(
            'NewZohoData').getValue(6, $i))

    WebUI.setText(findTestObject('Page_Create Member Lead - Zoho CRM/input_Zip_Crm_Potentials_POTENTIALCF5'), findTestData(
            'NewZohoData').getValue(8, $i))

    WebUI.click(findTestObject('Page_Create Member Lead - Zoho CRM/input_State_Crm_Potentials_POTENTIALCF02'))

    WebUI.setText(findTestObject('Page_Create Member Lead - Zoho CRM/input_State_Crm_Potentials_POTENTIALCF02'), findTestData(
            'NewZohoData').getValue(7, $i))

    WebUI.delay(3)
    WebUI.clickOffset(findTestObject('Page_Create Member Lead - Zoho CRM/input_State_Crm_Potentials_POTENTIALCF02'), 0, 
        55)

    WebUI.scrollToElement(findTestObject('Page_Create Member Lead - Zoho CRM/div_Export in progress_tcell vam pL20 pR10 crmLogoCont'), 
        5)

    WebUI.click(findTestObject('Page_Create Member Lead - Zoho CRM/input_Enriched data available_save'))

    WebUI.delay(10)
}

YIKES!! What a nightmare!

This is just for data-driven member-leads test case. As you could imagine, this test case was a nightmare to reason about, let alone maintain…

and even more of a nightmare to build a member-lead test suite off of… If you were to use this test case to build another one for another scenario (e.g. a sanity test case), that would mean having to go back and replacing every damn findTestData().getValue() call with the actual variable/value!

And with this non-object-oriented code, given a test suite consisting of 25 other test cases for member lead, I would had to have done that times 25! :exploding_head:

Thank fuck I decided to refactor this ASAP!

Changes I made…

Several changes had to be made to this, way more than I want to enumerate on here. Some of the first ones include:

  • removing duplicate code from if-condition blocks,
  • getting rid of WebUI.delay()s,
  • creating and using enum types and maps, instead of all the if-conditions, and finally
  • switching to an object-oriented (i.e. model-driven) test case design, and to using model list builders, instead of the TestData

The enums, builders, and models were written as custom keywords .

The test case before the data-refactor

Looked like this:

import static com.kms.katalon.core.testdata.TestDataFactory.findTestData
import static com.kms.katalon.core.testobject.ObjectRepository.findTestObject
import com.kms.katalon.core.webui.keyword.WebUiBuiltInKeywords as WebUI
import com.signaturemd.enums.MemberCategory as MemberCategory
import com.signaturemd.enums.MemberLeadType as MemberLeadType
import com.signaturemd.enums.MemberType as MemberType
import com.kms.katalon.core.mobile.keyword.MobileBuiltInKeywords as Mobile
import com.kms.katalon.core.cucumber.keyword.CucumberBuiltinKeywords as CucumberKW
import com.kms.katalon.core.webservice.keyword.WSBuiltInKeywords as WS
import com.kms.katalon.core.windows.keyword.WindowsBuiltinKeywords as Windows
import static com.kms.katalon.core.testobject.ObjectRepository.findWindowsObject
import static com.kms.katalon.core.testcase.TestCaseFactory.findTestCase
import static com.kms.katalon.core.checkpoint.CheckpointFactory.findCheckpoint
import com.kms.katalon.core.model.FailureHandling as FailureHandling
import com.kms.katalon.core.testcase.TestCase as TestCase
import com.kms.katalon.core.testdata.TestData as TestData
import com.kms.katalon.core.testobject.TestObject as TestObject
import com.kms.katalon.core.checkpoint.Checkpoint as Checkpoint
import internal.GlobalVariable as GlobalVariable

for ($i = 1; $i <= findTestData('NewZohoData').getRowNumbers(); $i++) {
    WebUI.navigateToUrl(findTestData('NewZohoData').getValue(11, $i))

    WebUI.scrollToElement(findTestObject('Page_Red Group Practice (Practice) - Zoho CRM/div_PersonnelOffice DetailsMember LeadMember DetailsExpensesEarnout DetailBuyout Details'), 
        5)

    WebUI.click(findTestObject('Page_Practice - Zoho CRM/Fourth Row Section/Tabs/span_Member Lead'))

    WebUI.click(findTestObject('Page_Red Group Practice (Practice) - Zoho CRM/lyte-yield_New Member Lead'))

    WebUI.setText(findTestObject('Page_Create Member Lead - Zoho CRM/textarea_DescriptionNotes_Crm_Potentials_POTENTIALCF125'), 
        'This is a description of the Member Lead')

    WebUI.setText(findTestObject('Page_Create Member Lead - Zoho CRM/input_First Name_Crm_Potentials_POTENTIALCF21'), findTestData(
            'NewZohoData').getValue(1, $i))

    WebUI.setText(findTestObject('Page_Create Member Lead - Zoho CRM/input_Last Name_Crm_Potentials_POTENTIALCF20'), findTestData(
            'NewZohoData').getValue(2, $i))

    WebUI.setText(findTestObject('Page_Create Member Lead - Zoho CRM/input_Email_Crm_Potentials_POTENTIALCF14'), findTestData(
            'NewZohoData').getValue(9, $i))

    WebUI.setText(findTestObject('Page_Create Member Lead - Zoho CRM/input_Home Phone Number_Crm_Potentials_POTENTIALCF18'), 
        findTestData('NewZohoData').getValue(3, $i))

    WebUI.setText(findTestObject('Page_Create Member Lead - Zoho CRM/input_Date of Birth_Crm_Potentials_POTENTIALCF81'), 
        findTestData('NewZohoData').getValue(17, $i))

    WebUI.scrollToElement(findTestObject('Page_Create Member Lead - Zoho CRM/td_Member Lead Information'), 0)

    WebUI.click(findTestObject('Page_Create Member Lead - Zoho CRM/input_Organization_Crm_Potentials_POTENTIALCF114'))

    WebUI.click(findTestObject('Page_Create Member Lead - Zoho CRM/span_SMD-BETA'))

    WebUI.click(findTestObject('Page_Create Member Lead - Zoho CRM/Member Lead Information section/Member Lead Type dropdown/Member Lead Type Dropdown button'))

    //Pick initial Type
    MemberLeadType memberLeadType = MemberLeadType.valueOfText(findTestData('NewZohoData').getValue(13, $i))

    if (memberLeadType.equals(MemberLeadType.INDIVIDUAL)) {
        WebUI.click(findTestObject('Page_Create Member Lead - Zoho CRM/Member Lead Information section/Member Lead Type dropdown/Individual Member Lead Type dropdown option'))
    } else if (memberLeadType.equals(MemberLeadType.CORPORATE)) {
        WebUI.click(findTestObject('Page_Create Member Lead - Zoho CRM/Member Lead Information section/Member Lead Type dropdown/Corporate Member Lead Type dropdown option'))
    } else {
        WebUI.click(findTestObject('Page_Create Member Lead - Zoho CRM/Member Lead Information section/Member Lead Type dropdown/Family Member Lead Type dropdown option'))
    }
    
    WebUI.click(findTestObject('Page_Create Member Lead - Zoho CRM/Member Lead Information section/Member Type dropdown/Member Type Dropdown button'))

    //Need to do the same for Member Type somehow....
    MemberType memberType = MemberType.valueOfText(findTestData('NewZohoData').getValue(14, $i))

    if (memberType.equals(MemberType.INDIVIDUAL)) {
        WebUI.click(findTestObject('Page_Create Member Lead - Zoho CRM/Member Lead Information section/Member Type dropdown/Individual Member Type dropdown option'))
    } else {
        WebUI.click(findTestObject('Page_Create Member Lead - Zoho CRM/Member Lead Information section/Member Type dropdown/Family Member Type dropdown option'))

        WebUI.setText(findTestObject('Page_Create Member Lead - Zoho CRM/input_Related Family Member_Crm_Potentials_POTENTIALCF01'), 
            findTestData('NewZohoData').getValue(15, $i))

        WebUI.waitForElementClickable(findTestObject('Page_Create Member Lead - Zoho CRM/Member Lead Information section/Related Family Member dropdown/First related family member dropdown option'), 
            2)

        WebUI.click(findTestObject('Page_Create Member Lead - Zoho CRM/Member Lead Information section/Related Family Member dropdown/First related family member dropdown option'))
    }
    
    WebUI.setText(findTestObject('Page_Create Member Lead - Zoho CRM/input_Lead Date_Crm_Potentials_POTENTIALCF82'), findTestData(
            'NewZohoData').getValue(18, $i))

    if (findTestData('NewZohoData').getValue(19, $i) == 'Y') {
        WebUI.click(findTestObject('Page_Create Member Lead - Zoho CRM/input_Back Date_Crm_Potentials_POTENTIALCF108'))

        WebUI.setText(findTestObject('Page_Create Member Lead - Zoho CRM/input_Tentative Contract Start Date_Crm_Potentials_POTENTIALCF84'), 
            findTestData('NewZohoData').getValue(20, $i))
    }
    
    MemberCategory memberCategory = MemberCategory.valueOfText(findTestData('NewZohoData').getValue(12, $i))

    WebUI.sendKeys(findTestObject('Page_Create Member Lead - Zoho CRM/Member Lead Information section/Member Category autocomplete/Member Category autocomplete'), 
        memberCategory.textValue)

    WebUI.waitForElementVisible(findTestObject('Page_Create Member Lead - Zoho CRM/Member Lead Information section/Member Category autocomplete/Autocomplete loader'), 
        2)

    WebUI.waitForElementNotVisible(findTestObject('Page_Create Member Lead - Zoho CRM/Member Lead Information section/Member Category autocomplete/Autocomplete loader'), 
        2)

    if (memberCategory.equals(MemberCategory.MEMBERSHIP)) {
        WebUI.click(findTestObject('Page_Create Member Lead - Zoho CRM/span_Membership'))
    } else if (memberCategory.equals(MemberCategory.PEDIATRIC)) {
        WebUI.clickOffset(findTestObject('Page_Create Member Lead - Zoho CRM/input_Member Category_Crm_Potentials_POTENTIALCF04'), 
            0, 40)
    } else if (memberCategory.equals(MemberCategory.STANDARD_MEMBERSHIP)) {
        WebUI.click(findTestObject('Page_Create Member Lead - Zoho CRM/span_Standard Membership'))
    } else if (memberCategory.equals(MemberCategory.SILVER_MEMBERSHIP)) {
        WebUI.click(findTestObject('Page_Create Member Lead - Zoho CRM/span_Silver Membership'))
    } else if (memberCategory.equals(MemberCategory.GOLD_MEMBERSHIP)) {
        WebUI.click(findTestObject('Page_Create Member Lead - Zoho CRM/span_Gold Membership'))
    }
    
    if (findTestData('NewZohoData').getValue(16, $i) == 'S') {
        WebUI.click(findTestObject('Page_Create Member Lead - Zoho CRM/span_Annual'))

        WebUI.clickOffset(findTestObject('Page_Create Member Lead - Zoho CRM/span_Annual'), -100, 100)
    } else if (findTestData('NewZohoData').getValue(16, $i) == 'Q') {
        WebUI.click(findTestObject('Page_Create Member Lead - Zoho CRM/span_Annual'))

        WebUI.clickOffset(findTestObject('Page_Create Member Lead - Zoho CRM/span_Annual'), -100, 135)
    } else if (findTestData('NewZohoData').getValue(16, $i) == 'M') {
        WebUI.click(findTestObject('Page_Create Member Lead - Zoho CRM/span_Annual'))

        WebUI.clickOffset(findTestObject('Page_Create Member Lead - Zoho CRM/span_Annual'), -100, 170)
    }
    
    WebUI.click(findTestObject('Page_Create Member Lead - Zoho CRM/span_-None-'))

    String paymentModeText = findTestData('NewZohoData').getValue(21, $i)

    if (paymentModeText == 'Check') {
        WebUI.click(findTestObject('Page_Create Member Lead - Zoho CRM/Member Lead Information section/Payment Mode dropdown/Check dropdown option'))
    } else if (paymentModeText == 'ACH') {
        WebUI.click(findTestObject('Page_Create Member Lead - Zoho CRM/Member Lead Information section/Payment Mode dropdown/ACH dropdown option'))
    } else if (paymentModeText == 'Credit Card') {
        WebUI.click(findTestObject('Page_Create Member Lead - Zoho CRM/Member Lead Information section/Payment Mode dropdown/Credit Card dropdown option'))
    }
    
    //Scroll to Address
    WebUI.scrollToElement(findTestObject('Page_Create Member Lead - Zoho CRM/td_Address Information'), 0)

    WebUI.setText(findTestObject('Page_Create Member Lead - Zoho CRM/input_Address Line 1_Crm_Potentials_POTENTIALCF7'), 
        findTestData('NewZohoData').getValue(4, $i))

    WebUI.setText(findTestObject('Page_Create Member Lead - Zoho CRM/input_Address Line 2_Crm_Potentials_POTENTIALCF8'), 
        findTestData('NewZohoData').getValue(5, $i))

    WebUI.setText(findTestObject('Page_Create Member Lead - Zoho CRM/input_City_Crm_Potentials_POTENTIALCF2'), findTestData(
            'NewZohoData').getValue(6, $i))

    WebUI.setText(findTestObject('Page_Create Member Lead - Zoho CRM/input_Zip_Crm_Potentials_POTENTIALCF5'), findTestData(
            'NewZohoData').getValue(8, $i))

    WebUI.click(findTestObject('Page_Create Member Lead - Zoho CRM/input_State_Crm_Potentials_POTENTIALCF02'))

    WebUI.setText(findTestObject('Page_Create Member Lead - Zoho CRM/input_State_Crm_Potentials_POTENTIALCF02'), findTestData(
            'NewZohoData').getValue(7, $i))

    WebUI.delay(3)

    WebUI.clickOffset(findTestObject('Page_Create Member Lead - Zoho CRM/input_State_Crm_Potentials_POTENTIALCF02'), 0, 
        55)

    WebUI.scrollToElement(findTestObject('Page_Create Member Lead - Zoho CRM/div_Export in progress_tcell vam pL20 pR10 crmLogoCont'), 
        5)

    WebUI.click(findTestObject('Page_Create Member Lead - Zoho CRM/input_Enriched data available_save'))

    WebUI.delay(20)
}

There are some code smells in here, such as WebUI.clickOffset() and WebUI.delay(), but those are subject of another blog post :slight_smile: I just linked one!

For this one, let’s discuss the data-refactoring…

Builders…

…are NOT necessarily that coupled-with-your-model, Gang-of-Four implementation. You do NOT need to have some static inner class in your model class to implement one.

This implementation is still valid, and builds a list of models:

Our implementation of them

public abstract class BaseModelBuilder<T> {

	protected TestData testData;

	public BaseModelBuilder() {
		this.init();
	}

	public BaseModelBuilder(TestData testData) {
		this.testData = testData;
		this.init();
	}

	protected void init() {
		// implementation go here
	}

	public TestData getTestData() {
		return this.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)
}

This, as you guessed it, is going to be the base model builder that we extend whenever we need a list of models from a data file.

MemberLeadBuilder

This is the first-version of our MemberLeadBuilder. It has changed considerably since then (with the making of other design decisions, that I don’t want to get into here):

public class MemberLeadBuilder extends BaseModelBuilder<MemberLeadModel> {

    public MemberLeadBuilder() {
	super(findTestData('NewZohoData'))
    }

    @Override
    public MemberLeadModel createModelFromRow(List<Object> row) {
	return new MemberLeadModel(
		row[0],
		row[1],
		row[2],
		row[9],
		row[3],
		row[4],
		row[5],
		row[6],
		Integer.parseInt(row[7]),
		row[8],
		row[10],
		MemberCategory.valueOfText(row[11]),
		MemberLeadType.valueOfText(row[12]),
		MemberType.valueOfText(row[13]),
		row[14],
		Frequency.valueOfText(row[15]),
		Formats.DateFormat.parse(row[16]),
		(row[18] == 'Y'),
		Formats.DateFormat.parse(row[17]),
		Formats.DateFormat.parse(row[19]),
		PaymentMode.valueOfText(row[20]));
    }
}

yes we had to define our own MemberLeadModel.

Putting the builder pattern to use

After making all the aforementioned design changes (except there were still some WebUI.clickOffset()s still in the code. I slayed those later), my data-driven test case became:

for (MemberLeadModel model : new MemberLeadBuilder().createModels()) {
    WebUI.navigateToUrl(model.getPracticeLink())

    WebUI.scrollToElement(findTestObject('Page_Red Group Practice (Practice) - Zoho CRM/div_PersonnelOffice DetailsMember LeadMember DetailsExpensesEarnout DetailBuyout Details'), 
        5)

    WebUI.click(findTestObject('Page_Practice - Zoho CRM/Fourth Row Section/Tabs/span_Member Lead'))

    WebUI.click(findTestObject('Page_Red Group Practice (Practice) - Zoho CRM/lyte-yield_New Member Lead'))

    WebUI.setText(findTestObject('Page_Create Member Lead - Zoho CRM/textarea_DescriptionNotes_Crm_Potentials_POTENTIALCF125'), 
        'This is a description of the Member Lead')

    WebUI.setText(findTestObject('Page_Create Member Lead - Zoho CRM/input_First Name_Crm_Potentials_POTENTIALCF21'), model.getFirstName())

    WebUI.setText(findTestObject('Page_Create Member Lead - Zoho CRM/input_Last Name_Crm_Potentials_POTENTIALCF20'), model.getLastName())

    WebUI.setText(findTestObject('Page_Create Member Lead - Zoho CRM/input_Email_Crm_Potentials_POTENTIALCF14'), model.getEmail())

    WebUI.setText(findTestObject('Page_Create Member Lead - Zoho CRM/input_Home Phone Number_Crm_Potentials_POTENTIALCF18'), 
        model.getPhoneNumber())

    WebUI.setText(findTestObject('Page_Create Member Lead - Zoho CRM/input_Date of Birth_Crm_Potentials_POTENTIALCF81'), 
        Formats.DateFormat.format(model.getDob()))

    WebUI.scrollToElement(findTestObject('Page_Create Member Lead - Zoho CRM/td_Member Lead Information'), 0)

    WebUI.click(findTestObject('Page_Create Member Lead - Zoho CRM/input_Organization_Crm_Potentials_POTENTIALCF114'))

    WebUI.click(findTestObject('Page_Create Member Lead - Zoho CRM/span_SMD-BETA'))

    WebUI.click(findTestObject('Page_Create Member Lead - Zoho CRM/Member Lead Information section/Member Lead Type dropdown/Member Lead Type Dropdown button'))

    //Pick initial Type
    if (model.getMemberLeadType().equals(MemberLeadType.INDIVIDUAL)) {
        WebUI.click(findTestObject('Page_Create Member Lead - Zoho CRM/Member Lead Information section/Member Lead Type dropdown/Individual Member Lead Type dropdown option'))
    } else if (model.getMemberLeadType().equals(MemberLeadType.CORPORATE)) {
        WebUI.click(findTestObject('Page_Create Member Lead - Zoho CRM/Member Lead Information section/Member Lead Type dropdown/Corporate Member Lead Type dropdown option'))
    } else {
        WebUI.click(findTestObject('Page_Create Member Lead - Zoho CRM/Member Lead Information section/Member Lead Type dropdown/Family Member Lead Type dropdown option'))
    }
    
    WebUI.click(findTestObject('Page_Create Member Lead - Zoho CRM/Member Lead Information section/Member Type dropdown/Member Type Dropdown button'))

    //Need to do the same for Member Type somehow....
    if (model.getMemberType().equals(MemberType.INDIVIDUAL)) {
        WebUI.click(findTestObject('Page_Create Member Lead - Zoho CRM/Member Lead Information section/Member Type dropdown/Individual Member Type dropdown option'))
    } else {
        WebUI.click(findTestObject('Page_Create Member Lead - Zoho CRM/Member Lead Information section/Member Type dropdown/Family Member Type dropdown option'))

        WebUI.setText(findTestObject('Page_Create Member Lead - Zoho CRM/input_Related Family Member_Crm_Potentials_POTENTIALCF01'), 
            model.getRelatedFamily())

        WebUI.waitForElementClickable(findTestObject('Page_Create Member Lead - Zoho CRM/Member Lead Information section/Related Family Member dropdown/First related family member dropdown option'), 
            2)

        WebUI.click(findTestObject('Page_Create Member Lead - Zoho CRM/Member Lead Information section/Related Family Member dropdown/First related family member dropdown option'))
    }
    
    WebUI.setText(findTestObject('Page_Create Member Lead - Zoho CRM/input_Lead Date_Crm_Potentials_POTENTIALCF82'), Formats.DateFormat.format(
            model.getLeadDate()))

    if (model.isBackDated()) {
        WebUI.click(findTestObject('Page_Create Member Lead - Zoho CRM/input_Back Date_Crm_Potentials_POTENTIALCF108'))

        WebUI.setText(findTestObject('Page_Create Member Lead - Zoho CRM/input_Tentative Contract Start Date_Crm_Potentials_POTENTIALCF84'), 
            Formats.DateFormat.format(model.getContractStartDate()))
    }
    
    MemberCategory memberCategory = model.getMemberCategory()

    WebUI.sendKeys(findTestObject('Page_Create Member Lead - Zoho CRM/Member Lead Information section/Member Category autocomplete/Member Category autocomplete'), 
        memberCategory.textValue)

    WebUI.waitForElementVisible(findTestObject('Page_Create Member Lead - Zoho CRM/Member Lead Information section/Member Category autocomplete/Autocomplete loader'), 
        2)

    WebUI.waitForElementNotVisible(findTestObject('Page_Create Member Lead - Zoho CRM/Member Lead Information section/Member Category autocomplete/Autocomplete loader'), 
        2)

    if (memberCategory.equals(MemberCategory.MEMBERSHIP)) {
        WebUI.click(findTestObject('Page_Create Member Lead - Zoho CRM/Member Lead Information section/Member Category autocomplete/Membership dropdown option'))
    } else if (memberCategory.equals(MemberCategory.PEDIATRIC)) {
        WebUI.click(findTestObject('Page_Create Member Lead - Zoho CRM/Member Lead Information section/Member Category autocomplete/Pediatric dropdown option'))
    } else if (memberCategory.equals(MemberCategory.STANDARD_MEMBERSHIP)) {
        WebUI.click(findTestObject('Page_Create Member Lead - Zoho CRM/Member Lead Information section/Member Category autocomplete/Standard Membership dropdown option'))
    } else if (memberCategory.equals(MemberCategory.SILVER_MEMBERSHIP)) {
        WebUI.click(findTestObject('Page_Create Member Lead - Zoho CRM/Member Lead Information section/Member Category autocomplete/Silver Membership dropdown option'))
    } else if (memberCategory.equals(MemberCategory.GOLD_MEMBERSHIP)) {
        WebUI.click(findTestObject('Page_Create Member Lead - Zoho CRM/Member Lead Information section/Member Category autocomplete/Gold Membership dropdown option'))
    }
    
    WebUI.click(findTestObject('Page_Create Member Lead - Zoho CRM/span_Annual'))

    if (model.getFrequency().equals(Frequency.SEMI_ANNUAL)) {
        WebUI.clickOffset(findTestObject('Page_Create Member Lead - Zoho CRM/span_Annual'), -100, 100)
    } else if (model.getFrequency().equals(Frequency.QUARTERLY)) {
        WebUI.clickOffset(findTestObject('Page_Create Member Lead - Zoho CRM/span_Annual'), -100, 135)
    } else if (model.getFrequency().equals(Frequency.MONTHLY)) {
        WebUI.clickOffset(findTestObject('Page_Create Member Lead - Zoho CRM/span_Annual'), -100, 170)
    }
    
    WebUI.click(findTestObject('Page_Create Member Lead - Zoho CRM/span_-None-'))

    if (model.getPaymentMode().equals(PaymentMode.CHECK)) {
        WebUI.click(findTestObject('Page_Create Member Lead - Zoho CRM/Member Lead Information section/Payment Mode dropdown/Check dropdown option'))
    } else if (model.getPaymentMode().equals(PaymentMode.ACH)) {
        WebUI.click(findTestObject('Page_Create Member Lead - Zoho CRM/Member Lead Information section/Payment Mode dropdown/ACH dropdown option'))
    } else if (model.getPaymentMode().equals(PaymentMode.CREDIT_CARD)) {
        WebUI.click(findTestObject('Page_Create Member Lead - Zoho CRM/Member Lead Information section/Payment Mode dropdown/Credit Card dropdown option'))
    }
    
    //Scroll to Address
    WebUI.scrollToElement(findTestObject('Page_Create Member Lead - Zoho CRM/td_Address Information'), 0)

    WebUI.setText(findTestObject('Page_Create Member Lead - Zoho CRM/input_Address Line 1_Crm_Potentials_POTENTIALCF7'), 
        model.getAddress())

    WebUI.setText(findTestObject('Page_Create Member Lead - Zoho CRM/input_Address Line 2_Crm_Potentials_POTENTIALCF8'), 
        model.getAddress2())

    WebUI.setText(findTestObject('Page_Create Member Lead - Zoho CRM/input_City_Crm_Potentials_POTENTIALCF2'), model.getCity())

    WebUI.setText(findTestObject('Page_Create Member Lead - Zoho CRM/input_Zip_Crm_Potentials_POTENTIALCF5'), model.getZip().toString())

    WebUI.click(findTestObject('Page_Create Member Lead - Zoho CRM/input_State_Crm_Potentials_POTENTIALCF02'))

    WebUI.setText(findTestObject('Page_Create Member Lead - Zoho CRM/input_State_Crm_Potentials_POTENTIALCF02'), model.getState())

    WebUI.waitForElementVisible(findTestObject('Page_Create Member Lead - Zoho CRM/Address Information section/State Autocomplete/State loader'), 
        3)

    WebUI.waitForElementVisible(findTestObject('Page_Create Member Lead - Zoho CRM/Address Information section/State Autocomplete/First State dropdown option'), 
        3)

    WebUI.click(findTestObject('Page_Create Member Lead - Zoho CRM/Address Information section/State Autocomplete/First State dropdown option'))

    WebUI.scrollToElement(findTestObject('Page_Create Member Lead - Zoho CRM/div_Export in progress_tcell vam pL20 pR10 crmLogoCont'), 
        5)

    WebUI.submit(findTestObject('Page_Zoho shared repository/Practice subpages/Main form/Main form'))

    WebUI.waitForElementNotPresent(findTestObject('Page_Create Member Lead - Zoho CRM/input_Enriched data available_save'), 
        5)

    WebUI.waitForPageLoad(5)

    WebUI.verifyEqual(WebUI.getUrl(), model.getPracticeLink())
}

Completing test suite off of this one test case

Is now literally a matter of copy-paste-change (or delete)…

Now, for literally every other member lead test case scenario, I just :

  • copy the sanity test case and
  • remove whatever if-conditions I don’t need for that test case, and if applicable (i.e. for negative test cases or bugs or edge cases),
  • declare some variable with some super-descriptive name at the top of the script (e.g. final String futureDob = Formats.DateFormat.format(model.getDob())), and
  • add in any error-widget-expectations as needed .
  • change name to whatever it is you’re testing.

Voila! You got a whole new test case, with just a couple minutes of effort!

How to create the sanity test case? Simple.

  • copy this data-list-driven one,
  • replace the for loop, with a member lead factory method (this will be another blog post)

Need a parameterized test case, that will serve as a child test case? Just

  • create that model as test case variable, default to null
  • cast that model as the target data type (in my case for this example MemberLeadModel) at the top of the test script

There will be a part two to this blog post coming soon: dealing with models that have other info from other data files (e.g. child models)…

Thoughts?

Concerns? Questions? Suggestions? Let’s hear them in the comments section below!

4 Likes

Awesome @mwarren04011990 ! Thank you for sharing such good tips to our community.