I have published a GitHub project
Here I am going to explain what I have done to test a Blog app using 2 browser windows simultaneously. I used Katalon Studio. I wrote my test scripts in 2 ways; one in the typical Katalon Studio style, another using Page Object Model
This project is meant to be a set of sample codes for myself to develop a large scale test suite in future.
Movie for demonstration
For those who don’t have time, please have a look at the following movie. This shows how my Web UI test works.
Problem to solve
I want to answer to a question raised in the Katalon Forum with a runnable sample code set.
Please imagine. I can create 2 users to be authenticated by the web app. I would open 2 windows of Chrome browsers simultaneously. From each Chrome, I would visit the http://127.0.0.1/ as 2 users each. When a user “Alice” made a post, then another user “Bob” should be able to see the post by Alice in an instant. When Bob made a new post, then soon Alice should be able to see the Bob’s post.
This test scenario — testing a web app with 2 browsers simultaneously — can be extended to business use cases. Suppose that I have an EC site which has dual user interface: Customer UI and Administrator UI. When a user submit an order to purchase some products, then an administrator should be able to see the order in the list of outstanding orders. I want to test both of the Customer UI and the Administrator UI at the same time. My Web UI test should simulate submitting an order in the Customer UI; then my test my test should verify if the order is appearing in the Administrator UI. I want my test to simulate such dual-participants’ interaction.
But how can I open 2 browsers simultaneously in Katalon Studio?
There is a basic problem in Katalon Studio. Using WebUI.openBrowser()
keyword, you can not open 2 browsers.
I made a Test Case Test Cases/analysis/WebUI_openBrowser_twice in Katalon Studio to demonstrate this problem.
import com.kms.katalon.core.webui.keyword.WebUiBuiltInKeywords as WebUI
WebUI.openBrowser("http://127.0.0.1/")
WebUI.openBrowser("http://127.0.0.1/")
WebUI.delay(1)
WebUI.closeBrowser()
This simple script calls WebUI.openBrowser()
keyword twice. Do we see 2 windows of browsers opened? — No. We will see only 1 window opened, we do not see the 2nd window opened.
This way the WebUI.openBrowser()
is designed. You can not open 2 browses using this keyword.
Solution
opening browsers by WebDriver API
Behind the WebUI.openBrowser()
and other WebUI.xxx
keywords , an instance of Selenium WebDriver is working. If I write a script that makes an instances of WebDriver
class by calling org.openwa.selenium.chrome.ChromeDriver
directly, then I can open a Chrome browser. My script can create 2 instances of WebDriver
and keep them running. Then I will have 2 windows of Chrome browser. My test script can talk to them via the WebDriver API such as driver.navigate().to("http://127.0.0.1/")
.
While opening browsers with WebDriver API, still I want to use WebUI.xxx
keywords. There is a pitfall. Katalon’s WebUI.xxx
keyword do not work with a browser (a WebDriver
instance) that my script instantiated. Let me show you an experiment.
Test Cases/analysis/2_WebUI_keywords_do_not_know
String chrome_executable_path = DriverFactory.getChromeDriverPath()
System.setProperty('webdriver.chrome.driver', chrome_executable_path)
WebDriver browser = new ChromeDriver()
browser.navigate().to('http://127.0.0.1/')
// WebUI.xxx do not know the WebDriver instance created here
String windowTitle = WebUI.getWindowTitle()
assert "Posts - Flaskr" == windowTitle
This script opens a Chrome browser window by calling new ChromeDriver()
. But the script does not inform Katalon Studio of the WebDriver instance. WebUI keywords are not aware of the browser. Therefore calling WebUI.getWindowTitle()
keyword fails.
informing Katalon Studio of browsers opened by WebDriver API
How to fix this error? — call DriverFactory.changeWebDriver(WebDriver browser)
.
TestCases/analysis/3_how_to_inform_WebUI_keywords
import org.openqa.selenium.WebDriver
import org.openqa.selenium.chrome.ChromeDriver
import com.kms.katalon.core.webui.driver.DriverFactory
import com.kms.katalon.core.webui.keyword.WebUiBuiltInKeywords as WebUI
String chrome_executable_path = DriverFactory.getChromeDriverPath()
System.setProperty('webdriver.chrome.driver', chrome_executable_path)
WebDriver browser = new ChromeDriver()
browser.navigate().to('http://127.0.0.1/')
// i can let WebUI.xxx keywords know the WebDriver instance created by my script
DriverFactory.changeWebDriver(browser)
String windowTitle = WebUI.getWindowTitle()
assert "Posts - Flaskr" == windowTitle
This code passes.
Now WebUI.xxx
keywords can interact with the browser which was created by my script using new ChromeDriver()
API.
Waiting for the page to load
By a call driver.navigate().to("http://127.0.0.1/")
, we can open a browser and let it navigate to the URL specified. But this call does NOT perform implicit wait for the page to load completely. If you want to ensure that the page has been loaded, you need to do it explicitly.
There are several ways of implementing “wait for page to load”. The following sample code shows how to use WebUI.verifyElementPresent(TestObject, int timeout)
keyword.
// Test Cases/analysis/4_wait_for_the_page_to_load
import org.openqa.selenium.WebDriver
import org.openqa.selenium.chrome.ChromeDriver
import com.kms.katalon.core.model.FailureHandling
import com.kms.katalon.core.testobject.ConditionType
import com.kms.katalon.core.testobject.TestObject
import com.kms.katalon.core.webui.driver.DriverFactory
import com.kms.katalon.core.webui.keyword.WebUiBuiltInKeywords as WebUI
String chrome_executable_path = DriverFactory.getChromeDriverPath()
System.setProperty('webdriver.chrome.driver', chrome_executable_path)
WebDriver browser = new ChromeDriver()
browser.navigate().to('http://127.0.0.1/')
// i can let WebUI.xxx keywords know the WebDriver instance created by my script
DriverFactory.changeWebDriver(browser)
// wait for the page to load
TestObject tObj = makeTestObject("site_name", "//h1[text()='Flaskr']")
//TestObject tObj = makeTestObject("site_name", "//h1[text()='FlaskR']") // this will fail
WebUI.verifyElementPresent(tObj, 5, FailureHandling.STOP_ON_FAILURE)
WebUI.closeBrowser()
// helper method to create an instance of TestObject
TestObject makeTestObject(String id, String xpath) {
TestObject tObj = new TestObject(id)
tObj.addProperty("xpath", ConditionType.EQUALS, xpath)
return tObj
}
By the way, as you know, the WebUI.openBrowser(String url)
keyword does implicit wait. How is its implicit wait implemented? — You can find the source of the keyword at OpenBrowserKeyword.groovy. You can start reading the source and find its internal implementation. I think that explicit wait by WebUI.verifyElementPresent()
keyword is easier in this case to implement, than trying to imitate the implicit wait by WebUI.openBrowser()
keyword.
Magic spells for opening 2 browsers
In short, the following is the magic spells you need to know.
- In Katalon Studio, test script can open 2 browsers by calling
new ChromeDriver()
API twice. - a test script can call
DriverFactory.changeWebDriver(WebDriver)
API so thatWebUI.xxx
keywords can interact with the browser which was created by the script.
you can find more info at FlaskrTestInKatalonStudio | Testing a Blog web app with 2 browser windows using Selenium WebDriver in Katalon Studio. Includes a sample test script in Page Object Model.
A set of running sample test cases is included. I used the design pattern “Page Object Model” as well.