Skip to content

Commit fc848bc

Browse files
committed
Add a new runner for SeCore tests.
This is very rough right now. To use: buck build --show-output java/server/test/org/openqa/selenium:server-with-tests && java -jar buck-out/gen/java/server/test/org/openqa/selenium/server-with-tests.jar & buck run //java/client/src/com/thoughtworks/selenium/corerunner:main -- -htmlSuite *firefox http://www.google.com http://localhost:8989/tests/TestGoogle.html There's still lots to do, notably: * Support roll ups * Ensure the assert and verify commands actually do something * Write results to a formatted output * Allow individual tests to override the base URL. But it's a start, and it correctly parses the suites.
1 parent 49a7905 commit fc848bc

File tree

13 files changed

+550
-0
lines changed

13 files changed

+550
-0
lines changed
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
java_binary(
2+
name = 'main',
3+
main_class = 'com.thoughtworks.selenium.corerunner.Main',
4+
deps = [
5+
':corerunner',
6+
],
7+
)
8+
9+
java_library(
10+
name = 'corerunner',
11+
srcs = glob(['*.java']),
12+
deps = [
13+
'//java/client/src/com/thoughtworks/selenium:selenium',
14+
'//java/client/src/com/thoughtworks/selenium/webdriven:webdriven',
15+
'//java/client/src/org/openqa/selenium:selenium',
16+
'//java/client/src/org/openqa/selenium/chrome:chrome',
17+
'//java/client/src/org/openqa/selenium/edge:edge',
18+
'//java/client/src/org/openqa/selenium/firefox:firefox',
19+
'//java/client/src/org/openqa/selenium/ie:ie',
20+
'//java/client/src/org/openqa/selenium/opera:opera',
21+
'//java/client/src/org/openqa/selenium/remote:remote',
22+
'//java/client/src/org/openqa/selenium/safari:safari',
23+
'//third_party/java/guava:guava',
24+
],
25+
visibility = [
26+
],
27+
)
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
package com.thoughtworks.selenium.corerunner;
2+
3+
import com.google.common.base.Preconditions;
4+
5+
import com.thoughtworks.selenium.Selenium;
6+
7+
import org.openqa.selenium.By;
8+
import org.openqa.selenium.WebDriver;
9+
import org.openqa.selenium.WebElement;
10+
11+
import java.util.List;
12+
13+
public class CoreTest {
14+
15+
private final String url;
16+
17+
public CoreTest(String url) {
18+
this.url = Preconditions.checkNotNull(url);
19+
}
20+
21+
public void run(Results results, WebDriver driver, Selenium selenium) {
22+
if (!driver.getCurrentUrl().equals(url)) {
23+
driver.get(url);
24+
}
25+
26+
// Are we running a suite or an individual test?
27+
List<WebElement> allTables = driver.findElements(By.id("suiteTable"));
28+
29+
if (allTables.isEmpty()) {
30+
new CoreTestCase(url).run(results, driver, selenium);
31+
} else {
32+
new CoreTestSuite(url).run(results, driver, selenium);
33+
}
34+
}
35+
}
Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
package com.thoughtworks.selenium.corerunner;
2+
3+
4+
import com.google.common.base.Preconditions;
5+
import com.google.common.collect.ImmutableList;
6+
7+
import com.thoughtworks.selenium.Selenium;
8+
9+
import org.openqa.selenium.JavascriptExecutor;
10+
import org.openqa.selenium.WebDriver;
11+
12+
import java.util.List;
13+
14+
public class CoreTestCase {
15+
16+
private String url;
17+
18+
public CoreTestCase(String url) {
19+
this.url = Preconditions.checkNotNull(url);
20+
}
21+
22+
public void run(Results results, WebDriver driver, Selenium selenium) {
23+
String currentUrl = driver.getCurrentUrl();
24+
if (!url.equals(currentUrl)) {
25+
driver.get(url);
26+
}
27+
28+
List<CoreTestStep> steps = findCommands(driver);
29+
for (CoreTestStep step : steps) {
30+
step.run(results, driver, selenium);
31+
}
32+
}
33+
34+
private List<CoreTestStep> findCommands(WebDriver driver) {
35+
// Let's just run and hide in the horror that is JS for the sake of speed.
36+
List<List<String>> rawSteps = (List<List<String>>) ((JavascriptExecutor) driver).executeScript(
37+
"var toReturn = [];\n" +
38+
"var tables = document.getElementsByTagName('table');\n" +
39+
"for (var i = 0; i < tables.length; i++) {" +
40+
" for (var rowCount = 0; rowCount < tables[i].rows.length; rowCount++) {\n" +
41+
" if (tables[i].rows[rowCount].cells.length < 3) {\n" +
42+
" continue;\n" +
43+
" }\n" +
44+
" var cells = tables[i].rows[rowCount].cells;\n" +
45+
" toReturn.push([cells[0].textContent, cells[1].textContent, cells[2].textContent]);\n" +
46+
" }\n" +
47+
"}\n" +
48+
"return toReturn;");
49+
50+
ImmutableList.Builder<CoreTestStep> steps = ImmutableList.builder();
51+
for (List<String> rawStep: rawSteps) {
52+
steps.add(new CoreTestStep(rawStep.get(0), rawStep.get(1), rawStep.get(2)));
53+
}
54+
return steps.build();
55+
}
56+
}
Lines changed: 168 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,168 @@
1+
package com.thoughtworks.selenium.corerunner;
2+
3+
import com.google.common.collect.ImmutableMap;
4+
5+
import com.thoughtworks.selenium.Selenium;
6+
import com.thoughtworks.selenium.SeleniumException;
7+
8+
import org.openqa.selenium.WebDriver;
9+
10+
import java.lang.reflect.Method;
11+
import java.util.HashSet;
12+
import java.util.Objects;
13+
import java.util.Set;
14+
15+
public class CoreTestStep {
16+
17+
private static ImmutableMap<String, SeleneseCommand> COMMANDS = buildCommands();
18+
private final SeleneseCommand seleneseCommand;
19+
private final String locator;
20+
private final String value;
21+
22+
public CoreTestStep(String command, String locator, String value) {
23+
seleneseCommand = COMMANDS.get(command);
24+
this.locator = locator;
25+
this.value = value;
26+
27+
if (seleneseCommand == null) {
28+
throw new SeleniumException("Unknown command: " + command);
29+
}
30+
}
31+
32+
public void run(Results results, WebDriver driver, Selenium selenium) {
33+
seleneseCommand.execute(driver, selenium, locator, value);
34+
}
35+
36+
private static ImmutableMap<String, SeleneseCommand> buildCommands() {
37+
ImmutableMap.Builder<String, SeleneseCommand> commands = ImmutableMap.builder();
38+
Set<String> seenNames = new HashSet<>();
39+
40+
// seed the seen names with methods we definitely don't want folks accessing
41+
seenNames.add("addCustomRequestHeader");
42+
seenNames.add("allowNativeXpath");
43+
seenNames.add("pause");
44+
seenNames.add("rollup");
45+
seenNames.add("setBrowserLogLevel");
46+
seenNames.add("setExtensionJs");
47+
seenNames.add("start");
48+
seenNames.add("stop");
49+
50+
for (final Method method : Selenium.class.getMethods()) {
51+
if (!seenNames.add(method.getName())) {
52+
continue;
53+
}
54+
55+
if (method.getParameterCount() > 3) {
56+
continue;
57+
}
58+
59+
SeleneseCommand underlyingCommand = (driver, selenium, locator, value) -> {
60+
try {
61+
switch (method.getParameterCount()) {
62+
case 0:
63+
return method.invoke(selenium);
64+
65+
case 1:
66+
return method.invoke(selenium, locator);
67+
68+
case 2:
69+
return method.invoke(selenium, locator, value);
70+
71+
default:
72+
throw new RuntimeException("Exceptionally unlikely to get here");
73+
}
74+
} catch (ReflectiveOperationException e) {
75+
throw new RuntimeException(e);
76+
}
77+
};
78+
commands.put(method.getName(), underlyingCommand);
79+
80+
// Methods of the form getFoo(target) result in commands:
81+
// getFoo, assertFoo, verifyFoo, assertNotFoo, verifyNotFoo
82+
// storeFoo, waitForFoo, and waitForNotFoo.
83+
final String shortName;
84+
if (method.getName().startsWith("get")) {
85+
shortName = method.getName().substring("get".length());
86+
} else if (method.getName().startsWith("is")) {
87+
shortName = method.getName().substring("is".length());
88+
} else {
89+
shortName = null;
90+
}
91+
92+
if (shortName != null) {
93+
SeleneseCommand performComparison = (driver, selenium, locator, value) -> {
94+
Object result = underlyingCommand.execute(driver, selenium, locator, value);
95+
if ("is".equals(shortName)) {
96+
return (Boolean) result;
97+
}
98+
99+
String comparisonValue;
100+
switch (method.getParameterCount()) {
101+
case 0:
102+
comparisonValue = locator;
103+
break;
104+
105+
case 1:
106+
comparisonValue = value;
107+
break;
108+
109+
default:
110+
throw new RuntimeException("Unsure how to process this assert: " + method.getName());
111+
}
112+
return Objects.equals(comparisonValue, String.valueOf(result));
113+
};
114+
115+
commands.put("assert" + shortName, (driver, selenium, locator, value) -> {
116+
boolean result = (Boolean) performComparison.execute(driver, selenium, locator, value);
117+
if (!result) {
118+
throw new SeleniumException("Assertion failed");
119+
}
120+
return null;
121+
});
122+
123+
commands.put("assertNot" + shortName, (driver, selenium, locator, value) -> {
124+
boolean result = (Boolean) performComparison.execute(driver, selenium, locator, value);
125+
if (result) {
126+
throw new SeleniumException("Negative assertion failed");
127+
}
128+
return null;
129+
});
130+
131+
commands.put("verify" + shortName, (driver, selenium, locator, value) -> {
132+
boolean result = (Boolean) performComparison.execute(driver, selenium, locator, value);
133+
if (!result) {
134+
System.out.println("Verification failed");
135+
}
136+
return null;
137+
});
138+
139+
commands.put("verifyNot" + shortName, (driver, selenium, locator, value) -> {
140+
boolean result = (Boolean) performComparison.execute(driver, selenium, locator, value);
141+
if (result) {
142+
System.out.println("Negative verification failed");
143+
}
144+
return null;
145+
});
146+
}
147+
}
148+
149+
commands.put("pause", (driver, selenium, locator, value) -> {
150+
try {
151+
long timeout = Long.parseLong(locator);
152+
Thread.sleep(timeout);
153+
return null;
154+
} catch (NumberFormatException e) {
155+
throw new SeleniumException("Unable to parse timeout: " + locator);
156+
} catch (InterruptedException e) {
157+
System.exit(255);
158+
throw new RuntimeException("We never get this far");
159+
}
160+
});
161+
162+
return commands.build();
163+
}
164+
165+
private interface SeleneseCommand {
166+
Object execute(WebDriver driver, Selenium selenium, String locator, String value);
167+
}
168+
}
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
package com.thoughtworks.selenium.corerunner;
2+
3+
import com.thoughtworks.selenium.Selenium;
4+
import com.thoughtworks.selenium.SeleniumException;
5+
6+
import org.openqa.selenium.By;
7+
import org.openqa.selenium.JavascriptExecutor;
8+
import org.openqa.selenium.WebDriver;
9+
import org.openqa.selenium.WebElement;
10+
11+
import java.util.List;
12+
13+
public class CoreTestSuite {
14+
15+
private String url;
16+
17+
public CoreTestSuite(String url) {
18+
this.url = url;
19+
}
20+
21+
public void run(Results results, WebDriver driver, Selenium selenium) {
22+
if (!url.equals(driver.getCurrentUrl())) {
23+
driver.get(url);
24+
}
25+
26+
List<WebElement> allTables = driver.findElements(By.id("suiteTable"));
27+
if (allTables.isEmpty()) {
28+
throw new SeleniumException("Unable to locate suite table: " + url);
29+
}
30+
31+
List<String> allTestUrls = (List<String>) ((JavascriptExecutor) driver).executeScript(
32+
"var toReturn = [];\n" +
33+
"for (var i = 0; i < arguments[0].rows.length; i++) {\n" +
34+
" if (arguments[0].rows[i].cells.length == 0) {\n" +
35+
" continue;\n" +
36+
" }\n" +
37+
" var cell = arguments[0].rows[i].cells[0];\n" +
38+
" if (!cell) { continue; }\n" +
39+
" var allLinks = cell.getElementsByTagName('a');\n" +
40+
" if (allLinks.length > 0) {\n" +
41+
" toReturn.push(allLinks[0].href);\n" +
42+
" }\n" +
43+
"}\n" +
44+
"return toReturn;\n",
45+
allTables.get(0));
46+
47+
for (String testUrl : allTestUrls) {
48+
new CoreTest(testUrl).run(results, driver, selenium);
49+
}
50+
}
51+
}

0 commit comments

Comments
 (0)