Forum Discussion

Achoubey's avatar
Achoubey
New Contributor
5 years ago

struggling with High maintenance cost due to UI changes

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!

  • BenoitB's avatar
    BenoitB
    5 years ago

    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);
            }
          },

     

     

  • tristaanogre's avatar
    tristaanogre
    Esteemed Contributor

    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.

    • BenoitB's avatar
      BenoitB
      Community Hero

      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);
              }
            },