Happy Business Starts Here

Highlighted
Zuora Alumni

Best Practices for Testing with Selenium

What are the best practices for using Selenium to drive Test Automation within Salesforce using Zuora's Managed Packages?



If you found my answer helpful, please give me a kudo ↑
Help others find answers faster by accepting my post as a solution √

Tags (1)
1 ACCEPTED SOLUTION

Accepted Solutions
Highlighted
Zuora Alumni

Re: Best Practices for Testing with Selenium

This is not an exhaustive coverage of Selenium, but a few common issues that most will face when using Selenium to drive Test automation

 

Page/Object Pattern

 

As much as possible, decouple the actual rendering/look-and-feel from the functionality under test, and the tests that cover them.

 

Here is a good starting reference: http://www.seleniumhq.org/docs/06_test_design_considerations.jsp#page-object-design-pattern

 

 

 

Locators

 

Long story short, avoid locators that are dependent upon Structure, or Rendering/Style

 

  • Do not use full path locators

  • Try to use precise locators with attributes which are not likely to change

  • Use partial matchers whenever possible 
    avoid this
    a[id=\"j_id0:j_id2:subscriberLogin:theForm:thePageBlock:j_id13:0:loginLink\"]
    instead try this whenever possible
    a[id*=\"loginLink\"]
  • Avoid using sequences that represent containing structures
    ex: 
    //*[@id=":2l"]/div[5]/div[1]/div[2]
  • Do not use CSS locators that are related to style and rendering

 

 

Direct URLs

 

Whenever possible, direclty load the URL

 

In Salesforce this is very convenient, as most objects can be directly loaded with their ID via the URL

 

here is an example function to extract and set the base URL

 

 

public URL getBaseUrl(){
	try {
		URL url = new URL( driver.getCurrentUrl() );
		int port = url.getPort();
		return new URL(url.getProtocol()+"://"+url.getHost()+(port>0?":"+port:""));
	} catch (MalformedURLException e) {
		throw new RuntimeException(e);
	}
}

 

and here's an example of loading

 

 

public void loadUrl(URL url){
	driver.get(url.toExternalForm());
}

 

 

 

Waiting

 

Always use a wait before you attempt an operation

 

Although there are some rare cases where you will have to code your own wait, first try to let Selenium do the waiting

 

Here's an example function

 

 

public WebElement waitUntilLoaded(By matcher, int seconds){

	FluentWait<WebDriver> wait = new WebDriverWait(driver,seconds).pollingEvery(100, TimeUnit.MILLISECONDS);

	WebElement we = wait.until(presenceOfElementLocated(matcher));

	return we;

}

 

Here's an example that does an explicit wait if that fails, up to a certain number of times

 

 

public WebElement click(By matcher, int timeout, int max_retries) {

	getWindowHandles();
		
	WebElement we = null;

	for(int i=0; i<max_retries; i++){

		try{

			we = waitUntilLoaded(matcher, timeout);

			we.click();

			break;

		}catch(Throwable t1){

			System.out.println(t1.getMessage());

			try {
				we = waitUntilClickable(matcher, timeout);
				Thread.sleep(10000);
			} catch (InterruptedException e) {
				throw new RuntimeException(e);
			} catch (Throwable t2){
				System.out.println(t2.getMessage());
			}
			
		}

} return we; }

 

Additional Reference

 



If you found my answer helpful, please give me a kudo ↑
Help others find answers faster by accepting my post as a solution √

View solution in original post

1 REPLY 1
Highlighted
Zuora Alumni

Re: Best Practices for Testing with Selenium

This is not an exhaustive coverage of Selenium, but a few common issues that most will face when using Selenium to drive Test automation

 

Page/Object Pattern

 

As much as possible, decouple the actual rendering/look-and-feel from the functionality under test, and the tests that cover them.

 

Here is a good starting reference: http://www.seleniumhq.org/docs/06_test_design_considerations.jsp#page-object-design-pattern

 

 

 

Locators

 

Long story short, avoid locators that are dependent upon Structure, or Rendering/Style

 

  • Do not use full path locators

  • Try to use precise locators with attributes which are not likely to change

  • Use partial matchers whenever possible 
    avoid this
    a[id=\"j_id0:j_id2:subscriberLogin:theForm:thePageBlock:j_id13:0:loginLink\"]
    instead try this whenever possible
    a[id*=\"loginLink\"]
  • Avoid using sequences that represent containing structures
    ex: 
    //*[@id=":2l"]/div[5]/div[1]/div[2]
  • Do not use CSS locators that are related to style and rendering

 

 

Direct URLs

 

Whenever possible, direclty load the URL

 

In Salesforce this is very convenient, as most objects can be directly loaded with their ID via the URL

 

here is an example function to extract and set the base URL

 

 

public URL getBaseUrl(){
	try {
		URL url = new URL( driver.getCurrentUrl() );
		int port = url.getPort();
		return new URL(url.getProtocol()+"://"+url.getHost()+(port>0?":"+port:""));
	} catch (MalformedURLException e) {
		throw new RuntimeException(e);
	}
}

 

and here's an example of loading

 

 

public void loadUrl(URL url){
	driver.get(url.toExternalForm());
}

 

 

 

Waiting

 

Always use a wait before you attempt an operation

 

Although there are some rare cases where you will have to code your own wait, first try to let Selenium do the waiting

 

Here's an example function

 

 

public WebElement waitUntilLoaded(By matcher, int seconds){

	FluentWait<WebDriver> wait = new WebDriverWait(driver,seconds).pollingEvery(100, TimeUnit.MILLISECONDS);

	WebElement we = wait.until(presenceOfElementLocated(matcher));

	return we;

}

 

Here's an example that does an explicit wait if that fails, up to a certain number of times

 

 

public WebElement click(By matcher, int timeout, int max_retries) {

	getWindowHandles();
		
	WebElement we = null;

	for(int i=0; i<max_retries; i++){

		try{

			we = waitUntilLoaded(matcher, timeout);

			we.click();

			break;

		}catch(Throwable t1){

			System.out.println(t1.getMessage());

			try {
				we = waitUntilClickable(matcher, timeout);
				Thread.sleep(10000);
			} catch (InterruptedException e) {
				throw new RuntimeException(e);
			} catch (Throwable t2){
				System.out.println(t2.getMessage());
			}
			
		}

} return we; }

 

Additional Reference

 



If you found my answer helpful, please give me a kudo ↑
Help others find answers faster by accepting my post as a solution √

View solution in original post