Skip to content

Commit c18e8ad

Browse files
committed
added cross-platform parallelization
1 parent e93dfb2 commit c18e8ad

File tree

7 files changed

+260
-3
lines changed

7 files changed

+260
-3
lines changed

config/cross.testng.xml

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<!DOCTYPE suite SYSTEM "http://testng.org/testng-1.0.dtd">
3+
<suite name="Cross-Platform">
4+
<listeners>
5+
<listener class-name="XMLSuiteClassInterceptor"/>
6+
</listeners>
7+
<test name="PoolTest1" parallel="classes" thread-count="2">
8+
<parameter name="config" value="cross.conf.json"/>
9+
<classes>
10+
<class name="com.browserstack.suite.SuiteTest01"/>
11+
</classes>
12+
</test>
13+
<test name="PoolTest2" parallel="classes" thread-count="2">
14+
<parameter name="config" value="cross.conf.json"/>
15+
<classes>
16+
<class name="com.browserstack.suite.SuiteTest01"/>
17+
<class name="com.browserstack.suite.SuiteTest02"/>
18+
</classes>
19+
</test>
20+
</suite>
21+

pom.xml

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,14 @@
5555
<artifactId>maven-surefire-plugin</artifactId>
5656
<version>2.18.1</version>
5757
</plugin>
58+
<plugin>
59+
<groupId>org.apache.maven.plugins</groupId>
60+
<artifactId>maven-compiler-plugin</artifactId>
61+
<configuration>
62+
<source>1.8</source>
63+
<target>1.8</target>
64+
</configuration>
65+
</plugin>
5866
</plugins>
5967
</build>
6068

@@ -126,6 +134,21 @@
126134
</plugins>
127135
</build>
128136
</profile>
137+
<profile>
138+
<id>cross</id>
139+
<build>
140+
<plugins>
141+
<plugin>
142+
<groupId>org.apache.maven.plugins</groupId>
143+
<artifactId>maven-surefire-plugin</artifactId>
144+
<configuration>
145+
<suiteXmlFiles>
146+
<suiteXmlFile>config/cross.testng.xml</suiteXmlFile>
147+
</suiteXmlFiles>
148+
</configuration>
149+
</plugin>
150+
</plugins>
151+
</build>
152+
</profile>
129153
</profiles>
130-
131154
</project>
Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
import org.json.simple.JSONArray;
2+
import org.json.simple.JSONObject;
3+
import org.json.simple.parser.JSONParser;
4+
import org.json.simple.parser.ParseException;
5+
import org.testng.IAlterSuiteListener;
6+
import org.testng.xml.XmlSuite;
7+
import org.testng.xml.XmlTest;
8+
9+
import java.io.FileReader;
10+
import java.io.IOException;
11+
import java.util.HashMap;
12+
import java.util.List;
13+
import java.util.Map;
14+
import java.util.concurrent.CopyOnWriteArrayList;
15+
16+
public class XMLSuiteClassInterceptor implements IAlterSuiteListener {
17+
18+
@Override
19+
public void alter(List<XmlSuite> suites) {
20+
JSONParser parser = new JSONParser();
21+
int platformLength = 0;
22+
JSONArray platforms;
23+
try {
24+
JSONObject config = (JSONObject) parser.parse(new FileReader("src/test/resources/conf/cross.conf.json"));
25+
if (!config.isEmpty()) {
26+
platforms = (JSONArray) config.get("platforms");
27+
platformLength = platforms.size();
28+
}
29+
} catch (IOException | ParseException e) {
30+
throw new RuntimeException(e);
31+
}
32+
33+
int finalPlatformLength = platformLength;
34+
suites.forEach(suite -> {
35+
XmlTest[] testCloneArray = new XmlTest[suite.getTests().size()];
36+
List<XmlTest> newXmlTests = new CopyOnWriteArrayList<>();
37+
List<XmlTest> xmlTests = suite.getTests();
38+
int count = Integer.parseInt(String.valueOf(xmlTests.size()));
39+
40+
for (int i = 0; i < count; i++) {
41+
XmlTest testClone = (XmlTest) xmlTests.get(i).clone();
42+
xmlTests.get(i).addParameter("platform", "0");
43+
newXmlTests.add(xmlTests.get(i));
44+
testClone.setClasses(xmlTests.get(i).getClasses());
45+
testCloneArray[i] = testClone;
46+
}
47+
48+
if (finalPlatformLength > 1) {
49+
for (int index = 1; index < finalPlatformLength - 1; index++) {
50+
int cloneIndex = 0;
51+
for (XmlTest testClone : testCloneArray) {
52+
XmlTest tempclone = (XmlTest) testClone.clone();
53+
Map<String, String> map = tempclone.getAllParameters();
54+
map.put("platform", String.valueOf(index));
55+
tempclone.setClasses(testClone.getClasses());
56+
testClone.setParameters(map);
57+
newXmlTests.add(testClone);
58+
testCloneArray[cloneIndex] = tempclone;
59+
cloneIndex++;
60+
}
61+
}
62+
63+
for (XmlTest testClone : testCloneArray) {
64+
Map<String, String> map = testClone.getAllParameters();
65+
map.put("platform", String.valueOf(finalPlatformLength - 1));
66+
testClone.setParameters(map);
67+
newXmlTests.add(testClone);
68+
}
69+
}
70+
71+
suite.setTests(newXmlTests);
72+
});
73+
}
74+
}
Lines changed: 102 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,102 @@
1+
package com.browserstack;
2+
3+
import java.io.FileReader;
4+
import java.net.URL;
5+
import java.util.HashMap;
6+
import java.util.Iterator;
7+
import java.util.Map;
8+
9+
import com.browserstack.local.Local;
10+
11+
import org.json.simple.JSONArray;
12+
import org.json.simple.JSONObject;
13+
import org.json.simple.parser.JSONParser;
14+
import org.openqa.selenium.WebDriver;
15+
import org.openqa.selenium.remote.DesiredCapabilities;
16+
import org.openqa.selenium.remote.RemoteWebDriver;
17+
import org.testng.annotations.AfterMethod;
18+
import org.testng.annotations.BeforeMethod;
19+
20+
public class BrowserStackRemoteTest {
21+
public WebDriver driver;
22+
private Local l;
23+
24+
@BeforeMethod(alwaysRun = true)
25+
@org.testng.annotations.Parameters(value = { "config", "platform" })
26+
@SuppressWarnings("unchecked")
27+
public void setUp(String config_file, String platform) throws Exception {
28+
JSONParser parser = new JSONParser();
29+
JSONObject config;
30+
JSONArray platforms;
31+
if (!config_file.isEmpty()) {
32+
config = (JSONObject) parser.parse(new FileReader("src/test/resources/conf/" + config_file));
33+
platforms = (JSONArray) config.get("platforms");
34+
} else {
35+
config = (JSONObject) parser.parse("{}");
36+
String cliHub = System.getProperty("hub");
37+
if (cliHub.isEmpty()) {
38+
cliHub = "hub.browserstack.com";
39+
}
40+
config.put("server", cliHub);
41+
String cliUser = System.getProperty("userName");
42+
if (!cliUser.isEmpty()) {
43+
config.put("user", cliUser);
44+
}
45+
String cliKey = System.getProperty("accessKey");
46+
if (!cliKey.isEmpty()) {
47+
config.put("key", cliKey);
48+
}
49+
JSONObject cliCaps = (JSONObject) parser.parse(System.getProperty("caps").replaceAll("'", "\""));
50+
config.put("capabilities", cliCaps);
51+
JSONArray cliplatforms = (JSONArray) parser.parse(System.getProperty("platforms").replaceAll("'", "\""));
52+
platforms = cliplatforms;
53+
}
54+
55+
DesiredCapabilities capabilities = new DesiredCapabilities();
56+
Map<String, String> envCapabilities = (Map<String, String>) platforms.get(Integer.parseInt(platform));
57+
Iterator it = envCapabilities.entrySet().iterator();
58+
while (it.hasNext()) {
59+
Map.Entry pair = (Map.Entry) it.next();
60+
capabilities.setCapability(pair.getKey().toString(), pair.getValue().toString());
61+
}
62+
63+
Map<String, String> commonCapabilities = (Map<String, String>) config.get("capabilities");
64+
it = commonCapabilities.entrySet().iterator();
65+
while (it.hasNext()) {
66+
Map.Entry pair = (Map.Entry) it.next();
67+
if (capabilities.getCapability(pair.getKey().toString()) == null) {
68+
capabilities.setCapability(pair.getKey().toString(), pair.getValue().toString());
69+
}
70+
}
71+
72+
String username = System.getenv("BROWSERSTACK_USERNAME");
73+
if (username == null) {
74+
username = (String) config.get("user");
75+
}
76+
77+
String accessKey = System.getenv("BROWSERSTACK_ACCESS_KEY");
78+
if (accessKey == null) {
79+
accessKey = (String) config.get("key");
80+
}
81+
82+
if (capabilities.getCapability("browserstack.local") != null
83+
&& capabilities.getCapability("browserstack.local") == "true") {
84+
l = new Local();
85+
Map<String, String> options = new HashMap<String, String>();
86+
options.put("key", accessKey);
87+
l.start(options);
88+
}
89+
90+
driver = new RemoteWebDriver(
91+
new URL("https://" + username + ":" + accessKey + "@" + config.get("server") + "/wd/hub"), capabilities);
92+
}
93+
94+
@AfterMethod(alwaysRun = true)
95+
public void tearDown() throws Exception {
96+
driver.quit();
97+
if (l != null) {
98+
l.stop();
99+
}
100+
}
101+
}
102+

src/test/java/com/browserstack/suite/SuiteTest01.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
package com.browserstack.suite;
22

3+
import com.browserstack.BrowserStackRemoteTest;
34
import org.openqa.selenium.By;
45
import org.openqa.selenium.WebElement;
56

@@ -8,7 +9,7 @@
89

910
import com.browserstack.BrowserStackTestNGTest;
1011

11-
public class SuiteTest01 extends BrowserStackTestNGTest {
12+
public class SuiteTest01 extends BrowserStackRemoteTest {
1213

1314
@Test
1415
public void test_01() throws Exception {

src/test/java/com/browserstack/suite/SuiteTest02.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
package com.browserstack.suite;
22

3+
import com.browserstack.BrowserStackRemoteTest;
34
import org.openqa.selenium.By;
45
import org.openqa.selenium.WebElement;
56

@@ -8,7 +9,7 @@
89

910
import com.browserstack.BrowserStackTestNGTest;
1011

11-
public class SuiteTest02 extends BrowserStackTestNGTest {
12+
public class SuiteTest02 extends BrowserStackRemoteTest {
1213

1314
@Test
1415
public void test_02() throws Exception {
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
{
2+
"server": "hub-cloud.browserstack.com",
3+
"user": "BROWSERSTACK_USERNAME",
4+
"key": "BROWSERSTACK_ACCESS_KEY",
5+
6+
"capabilities": {
7+
"build": "browserstack-build-1",
8+
"name": "cross_platform_test",
9+
"browserstack.debug": true
10+
},
11+
12+
"platforms": [
13+
{
14+
"os": "OS X",
15+
"os_version": "Big Sur",
16+
"browser": "Chrome",
17+
"browser_version": "latest",
18+
"browserstack.selenium_version": "3.141.59"
19+
},
20+
{
21+
"os": "OS X",
22+
"os_version": "Catalina",
23+
"browser": "Safari",
24+
"browser_version": "latest",
25+
"browserstack.selenium_version": "3.141.59"
26+
},
27+
{
28+
"os": "OS X",
29+
"os_version": "Mojave",
30+
"browser": "Firefox",
31+
"browser_version": "latest",
32+
"browserstack.selenium_version": "3.141.59"
33+
}
34+
]
35+
}

0 commit comments

Comments
 (0)