QAF: Implementation of Self healing(Healenium) in QAF

Viewed 801

Am new to QAF and I need to implement self-healing in our test method using healenium. I have implemented it without QAF it's working fine. Please refer to the below code.

import com.epam.healenium.SelfHealingDriver;
import io.github.bonigarcia.wdm.WebDriverManager;
import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.BeforeAll;
import org.openqa.selenium.Dimension;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.chrome.ChromeDriver;
import org.openqa.selenium.chrome.ChromeOptions;

import java.util.concurrent.TimeUnit;

public class BaseTest {
    static protected SelfHealingDriver driver;

    @BeforeAll
    static public void setUp() {
        WebDriverManager.chromedriver().setup();
        ChromeOptions options = new ChromeOptions();
        options.setHeadless(false);
        //declare delegate
        WebDriver delegate = new ChromeDriver(options);
        driver = SelfHealingDriver.create(delegate);
        driver.manage().timeouts().implicitlyWait(4, TimeUnit.SECONDS);
        driver.manage().window().setSize(new Dimension(1200, 800));
    }

    @AfterAll
    static public void afterAll() {
        if (driver != null) {
            driver.quit();
        }
    }
}

I just want to wrap this self-healing driver with a QAF web driver like above.

1 Answers

QAF discourage to use static class variable for driver. The code provided in question will not work for parallel execution. Driver management is taken care by qaf with thread safety and with different behavior that can be set using property selenium.singletone.

You can try following way when you want SelfHealingDriver:

public class SampleTest extends WebDriverTestCase {

   @Test
   public void yourTestCase(){
      SelfHealingDriver driver = SelfHealingDriver.create(getDriver());
      //your code goes below
   }
}

SelfHealingDriver proxies actual driver. You can achieve the self heal functionality without driver proxy with listener for findelement/findChildelement. Driver listener should work without proxing driver. For example:

public class WDListener extends QAFWebDriverCommandAdapter {

private static final Map<String, Object> byToString = JSONUtil.toMap(
            "{'ByCssSelector':'css selector','ByClassName':'class name','ByXPath':'xpath','ByPartialLinkText':'partial link text','ById':'id','ByLinkText':'link text','ByName':'name'}");

   //this method will called when new driver object created
   public void onInitialize(QAFExtendedWebDriver driver){
        driver.manage().timeouts().implicitlyWait(4, TimeUnit.SECONDS);
        driver.manage().window().setSize(new Dimension(1200, 800));
   }

    @Override
    public void afterCommand(QAFExtendedWebDriver driver, CommandTracker commandTracker) {
        if (DriverCommand.FIND_ELEMENT.equalsIgnoreCase(commandTracker.getCommand())
                || DriverCommand.FIND_ELEMENTS.equalsIgnoreCase(commandTracker.getCommand())
                || DriverCommand.FIND_CHILD_ELEMENT.equalsIgnoreCase(commandTracker.getCommand())
                || DriverCommand.FIND_CHILD_ELEMENTS.equalsIgnoreCase(commandTracker.getCommand())) {
            Map<String, Object> parameters = commandTracker.getParameters();
            if (parameters != null && parameters.containsKey("using") && parameters.containsKey("value")) {
                By by = LocatorUtil
                        .getBy(String.format("%s=%s", parameters.get("using"), parameters.get("value")));
                
                HealingServiceImpl healingServiceImpl = new HealingServiceImpl(new SelfHealingEngine(driver));
                StackTraceElement[] stackTrace = Thread.currentThread().getStackTrace();
                Object result = commandTracker.getResponce().getValue();
                List<WebElement> webElements = List.class.isAssignableFrom(result.getClass())?(List<WebElement>) result:Collections.singletonList((WebElement)result)
                healingServiceImpl.savePath(new PageAwareBy(driver.getTitle(),by),webElements);
            }

        }
    }

    @Override
    public void onFailure(QAFExtendedWebDriver driver, CommandTracker commandTracker) {
        // StackTraceElement[] stackTrace =
        // commandTracker.getException().getStackTrace();

        Map<String, Object> parameters = commandTracker.getParameters();
        if (parameters != null && parameters.containsKey("using") && parameters.containsKey("value")) {
            By by = LocatorUtil
                    .getBy(String.format("%s=%s", parameters.get("using"), parameters.get("value")));
            StackTraceElement[] stackTrace = Thread.currentThread().getStackTrace();
            HealingServiceImpl healingServiceImpl = new HealingServiceImpl(new SelfHealingEngine(driver));

            Optional<By> healedBy = healingServiceImpl.healLocators(new PageAwareBy(driver.getTitle(),by), null, stackTrace) ;
            if(healedBy.isPresent()) {
            commandTracker.getParameters().putAll(toParams(healedBy.get()));
            commandTracker.setRetry(true);
            }
        }
    }
}
Related