Hello all:
We are having some major changes in a web application due to accessibility regulations in Canada.
Every release is coming with changes in the UI elements or panels.
This is resulting in high maintenance efforts for our automated testing suite.
Any idea , how to minimize such maintenance?
looks like XPath is not working for us.
Thanks in advance!
Solved! Go to Solution.
Hello,
Does the changes
- are no predictible at all ?
- are ui functional only ?
- are technical (name/type of field) also ?
These kind of change are always costly but you can optimize with some script logic.
I give you my way.
- Create one object/method by screen page.
- Input of each of these methods is a string of triplets; name of field:type of field=value or with a bi dimensional array.
- On your method do a loop on these values and for each element you know the name and type of the field to modify and the target value. So you can make a switch on the type for doing the correct action.
- You can also just make a switch on the name of the field, so UI changes is just adding the field in the switch.
Example for last option:
// *** PAGE IDENTIFICATION CONDUCTEUR ***
/* Edit:
Code postal zipCode
Nom cardholderSurname
Prénom cardholderFirstName
Numéro immatriculation plateNumber
Numéro série vehicleSerialNumber
Select:
Civilité title
Pays country
Case à cocher:
Titulaire carte grise isContractor, isDriver, isOther
Loi Hamon hasContractWithOtherInsurer
*/
saisieIdentificationConducteur:function(Data) {
let trace = this.methodStart("saisieIdentificationConducteur(" + Data + " ) - Saisie du formulaire Identification conducteur du contrat");
try {
let container = qa.system.findIt(Sys.Browser("*").Page("*"), "ObjectIdentifier", "policyVehicleForm", qa.system.time.longer, 15, true, true);
let recherche = Data.split(";");
let fields;
for (let i = 0; i < recherche.length; i++) {
if (recherche[i] != "") {
fields = recherche[i].split("=");
switch (fields[0]) {
case "souscripteurHamon" :
if (fields[1] == "oui")
qa.web.findItWeb("id", "hasContractWithOtherInsurer", "INPUT")[0].Click();
break;
case "titulaire" :
switch (fields[1]) {
case "conducteur" :
qa.web.findItWeb("id", "isDriver", "INPUT")[0].Click();
break;
case "souscripteur" :
qa.web.findItWeb("id", "isContractor", "INPUT")[0].Click();
break;
case "autre" :
qa.web.findItWeb("id", "isOther", "INPUT")[0].Click();
break;
}
break;
case "plateNumber" :
case "vehicleSerialNumber" :
case "cardholderSurname" :
case "cardholderFirstName" :
case "zipCode" :
qa.system.findIt(container, "ObjectIdentifier", fields[0], 0, 10, true, true).Keys(fields[1] + "[Tab]");
break;
case "title" :
case "country" :
qa.web.selectValueInHTMLCombo(fields[0], fields[1]);
break;
default :
throw Error("Saisie identification conducteur, champ '" + fields[0] + "' non géré/incorrect !");
}
}
}
this.etapeSuivante();
}
catch(e) {
errorString = qa.system.logExceptionByLevel(e, trace);
}
finally {
return this.methodStop(true);
}
},
Un sourire et ça repart
Generally speaking, a massive UI change is a rather large project for any UI based automation, whether it is using XPath or some other means.
For you... there may not be a way around this. If XPath isn't working at all, then your only bet is to refactor your method for object identification to use TestComplete's NameMapping functionality which would require a refactor of almost all your code.
Hello,
Does the changes
- are no predictible at all ?
- are ui functional only ?
- are technical (name/type of field) also ?
These kind of change are always costly but you can optimize with some script logic.
I give you my way.
- Create one object/method by screen page.
- Input of each of these methods is a string of triplets; name of field:type of field=value or with a bi dimensional array.
- On your method do a loop on these values and for each element you know the name and type of the field to modify and the target value. So you can make a switch on the type for doing the correct action.
- You can also just make a switch on the name of the field, so UI changes is just adding the field in the switch.
Example for last option:
// *** PAGE IDENTIFICATION CONDUCTEUR ***
/* Edit:
Code postal zipCode
Nom cardholderSurname
Prénom cardholderFirstName
Numéro immatriculation plateNumber
Numéro série vehicleSerialNumber
Select:
Civilité title
Pays country
Case à cocher:
Titulaire carte grise isContractor, isDriver, isOther
Loi Hamon hasContractWithOtherInsurer
*/
saisieIdentificationConducteur:function(Data) {
let trace = this.methodStart("saisieIdentificationConducteur(" + Data + " ) - Saisie du formulaire Identification conducteur du contrat");
try {
let container = qa.system.findIt(Sys.Browser("*").Page("*"), "ObjectIdentifier", "policyVehicleForm", qa.system.time.longer, 15, true, true);
let recherche = Data.split(";");
let fields;
for (let i = 0; i < recherche.length; i++) {
if (recherche[i] != "") {
fields = recherche[i].split("=");
switch (fields[0]) {
case "souscripteurHamon" :
if (fields[1] == "oui")
qa.web.findItWeb("id", "hasContractWithOtherInsurer", "INPUT")[0].Click();
break;
case "titulaire" :
switch (fields[1]) {
case "conducteur" :
qa.web.findItWeb("id", "isDriver", "INPUT")[0].Click();
break;
case "souscripteur" :
qa.web.findItWeb("id", "isContractor", "INPUT")[0].Click();
break;
case "autre" :
qa.web.findItWeb("id", "isOther", "INPUT")[0].Click();
break;
}
break;
case "plateNumber" :
case "vehicleSerialNumber" :
case "cardholderSurname" :
case "cardholderFirstName" :
case "zipCode" :
qa.system.findIt(container, "ObjectIdentifier", fields[0], 0, 10, true, true).Keys(fields[1] + "[Tab]");
break;
case "title" :
case "country" :
qa.web.selectValueInHTMLCombo(fields[0], fields[1]);
break;
default :
throw Error("Saisie identification conducteur, champ '" + fields[0] + "' non géré/incorrect !");
}
}
}
this.etapeSuivante();
}
catch(e) {
errorString = qa.system.logExceptionByLevel(e, trace);
}
finally {
return this.methodStop(true);
}
},
Un sourire et ça repart
Thanks I am certainly going to try it!
@BenoitB How have you identified ZipCode, CardholderSurname . I am from @Achoubey 's team, our primary issue is with the identification of the objects.
An example code :
if(aqObject.GetVarType(primaryEmail)== varEmpty)
Log.Message("Incorrect Primary Email is Displayed and Not exactly as per PARIS Database" + " " + primaryEmail);
else
Log.Message("Correct Primary Email is Displayed as per PARIS Database:" + " " + primaryEmail);
Here, we have identified primaryEmail as
var primaryEmail = page.EvaluateXPath("//span[text()[contains(.,'abc@optrust.com')]]")
or,
Sys.Browser("chrome").Page("*").Panel(0).Panel(0).Panel(0).Panel(1).Panel(2).Panel(0).Panel(0).Panel(0).Panel("pi_your_details").Panel(2).Panel(0).Panel(0).Panel(0).Panel(1).Panel(0).TextNode(1));
Both of these codes are vulnerable to UI Changes, the latter being more vulnerable when an accessibility change comes up when there were panels added at almost every ui element. We are looking to understand how to make it more robust.
Thanks,
I**bleep**a.
Dont use xpath only but use TC find method too.
XPath is the way that people working with webdriver knows, but TC is far more powerful and offers a better way of searching :
ParentObject.FindChildEx(Props, Values, Depth, Refresh, Timeout);
You have just to choose carefully what is the ParentObject. Is it the Page, a Form, a Panel ? Choose the one that don't change a lot.
In my example i create a placeholder (container) which is the form named policyVehicleForm of the current page. In this software, the form name don't change but fields were added/changed.
let container = qa.system.findIt(Sys.Browser("*").Page("*"), "ObjectIdentifier", "policyVehicleForm", qa.system.time.longer, 15, true, true);
Having that, when you have to add a new field to manage, just having its ID (ObjectName, ObjectIdentifier or whatever, introspect to find it or, better, ask to dev team to give it to you) and you search it in the container.
A sample call of my method is:
saisieIdentificationConducteur("titulaire=conducteur;souscripteurHamon=oui;plateNumber=65AQS45");
The way of building the input data is yours, you can use an Excel file to store fields name and value (recommanded way), you can build at run time or whatever.
Don't forget you can MIX both kind of search in same time Xpath and FindChild/FindChildEx.
Im my example some methods are mine, all starting with qa.. Just to know that qa.system.findIt is a method based on FindChildEx and qa.system.findWeb us a method based upon Xpath search.
Un sourire et ça repart
Thank you for the detailed explanation Benoit!
Hi @Achoubey! Does this help?
Thanks for the detailed expalanation @BenoitB . It was certainly helpful!
User | Count |
---|---|
14 | |
10 | |
7 | |
2 | |
1 |
Subject | Author | Latest Post |
---|---|---|