GEB :One class 测试用例未在单独的浏览器中打开
GEB :One class Test cases are not opening in separate browser
我从一个旧项目中导入了一个 class 名为“TestGebSpec”的项目。它的测试用例是 运行ning 在同一个浏览器上,所以我在 gebConfig.groovy 文件中添加了一个“CachingDriverFactory.clearCacheAndQuitDriver()”。不过,测试用例 运行 在同一个浏览器上运行,所以我创建了一个新的 groovy 测试用例文件“Login TC”
现在的问题是登录 TC 的测试用例 运行 在单独的浏览器上运行,即对于每个测试用例,都会启动一个新的驱动程序,但对于文件“TestGebSpec”,不知何故 TC 运行s在同一个浏览器上
有什么建议吗???
“TestGebSpec”文件的代码
@Stepwise
@SuppressWarnings(["GrUnresolvedAccess", "GroovyAssignabilityCheck", "UnnecessaryQualifiedReference"])
class KohlerSanityTestGebSpec extends GebReportingSpec {
public static final String USER_EMAIL = "test_user." + UUID.randomUUID() + "@kohler.com"
public static final String USER_PASSWORD = "pass123Word"
@Shared
productAddedToFolder
def setupSpec() {
driver.manage().window().maximize()
}
def setup() {}
def cleanup() {}
def cleanupSpec() {}
//--------------------------------------------------------------
// Utility methods start here.
//--------------------------------------------------------------
/** Using javascript runner to scroll an element into view so selenium can work with it. */
protected void scrollIntoViewJS(NonEmptyNavigator element) {
((JavascriptExecutor) driver).executeScript(
"arguments[0].scrollIntoView(true);",
element.firstElement());
sleep(1000)
}
protected void scrollUp(int distance) {
((JavascriptExecutor) driver).executeScript("scroll( 0, ${-distance});");
sleep(100)
}
protected void scrollDown(int distance) {
((JavascriptExecutor) driver).executeScript("scroll( 0, ${distance});");
sleep(100)
}
protected void hoverTest2(NonEmptyNavigator element) {
((JavascriptExecutor) driver).executeScript(
"arguments[0].trigger(\"hover\");",
element.firstElement());
}
protected void hoverOver(String path) {
org.openqa.selenium.WebElement element =
driver.findElement(org.openqa.selenium.By.cssSelector(path))
hoverOver(element)
}
protected void hoverOver(NonEmptyNavigator element) {
org.openqa.selenium.interactions.Actions builder = new
org.openqa.selenium.interactions.Actions(driver)
builder.moveToElement(element.getElement(0)).build().perform()
}
/** click, when the click() method does not work. */
@SuppressWarnings("GroovyUnusedDeclaration")
protected void clickElement(NonEmptyNavigator element) {
org.openqa.selenium.interactions.Actions builder = new org.openqa.selenium.interactions.Actions(driver)
builder.moveToElement(element.getElement(0)).click().build().perform()
}
protected void moveElement(NonEmptyNavigator handleElement, NonEmptyNavigator trackElement, int xPercent) {
org.openqa.selenium.WebElement handle = handleElement.getElement(0)
org.openqa.selenium.WebElement track = trackElement.getElement(0)
org.openqa.selenium.interactions.Actions builder = new org.openqa.selenium.interactions.Actions(driver)
int width = track.getSize().getWidth()
int moveLength = width * xPercent / 100
builder.dragAndDropBy(handle as org.openqa.selenium.WebElement, moveLength.intValue(), (int) 0).build().perform()
}
protected void closeSurveyPopup() {
if ($("#IPEbgCover")) {
$("area", alt: "close").click()
}
}
//----------------------------------------------------------------
// End of utility methods. Start of feature methods.
//----------------------------------------------------------------
def "Create project in bCC TESTCASE1"() {
browser.baseUrl = "URL"
when: "I log in to the BCC"
to BccLoginPage
loginForm.login = "data"
loginForm.$("#loginPassword").value("data")
$("input", type: "submit").click()
then:
at BccHomePage
when:
newCaProjectButton.click()
then:
at BccNewCaProject01Page
when: "I name and describe the new project."
def newProjectName = "gebtest-" + randomString(16, ('A'..'Z') + ('0'..'9'))
println "Creating BCC project \"$newProjectName\"."
projectNameInput.value(newProjectName)
projectDescriptionInput.value(randomString(50))
createProcessButton.click()
then:
at BccCaProjectDetailsPage
}
}
“登录TC”文件代码
class LoginTC extends GebReportingSpec{
def setupSpec() {
driver.manage().window().maximize()
//driver.manage().window().size = new org.openqa.selenium.Dimension( 1200, 1200 )
} // run before the first feature method
def setup() {} // run before every feature method
def cleanup() {} // run after every feature method
def cleanupSpec() {} // run after the last feature method
void "login tc2"(){
setup:
to HomePage
final String searchString = "string data"
searchInput = searchString
when:
btnSearch.click()
then:
at waitFor{ ProductDetailPage }
and:
sku.text().toLowerCase().contains( searchString.toLowerCase() )
}
void "login tc3"(){
setup:
to HomePage
final String searchString = "string data"
searchInput = searchString
when:
btnSearch.click()
then:
at waitFor{ ProductDetailPage }
}
}
简而言之,问题是为什么“TestGebSpec”文件 运行s 在同一浏览器上的功能
流程如下
1.Open 浏览器
2.Feature 1 运行
3.Feature 2 运行
.
.
.
最后一点。浏览器关闭
我除外
1.open 浏览器
2.Feature 1 运行
3.Close 浏览器
4.Open 浏览器
5.Feature 2 运行
6.Close 浏览器
实际上,如果下一个功能需要重新打开初始 URL,您网页上的错误应该不是问题。此外,cookie 应该不是问题,因为您可以手动或自动删除它们。过度使用 @Stepwise
也是许多用户问题的根源。你应该尽可能避免它。我什至看到您在只有一项功能的规范中使用它(或者您可能只向我展示了一项,但实际上还有更多)。使用许多浏览器是一种巨大的资源浪费,只会让你的测试变慢。 Geb 之书(手册)是极好的信息来源。
看看 implicit lifecycle with regard to clearCookies()
andclearWebStorage()
. Auto-clearing cookies and/or web storage 可能也会有所帮助。同一章还解释说,如果您只是在功能方法的末尾使用 CachingDriverFactory.clearCacheAndQuitDriver()
(或者如果您在每个功能中都需要它,则在 cleanup()
中),下一个方法将自动获取一个新的浏览器实例。
当然你可以quit the browser通过quit()
(退出浏览器)和close()
(关闭当前浏览器window)如果你想手动启动新浏览器.但是隐式驱动程序管理更容易使用 IMO,所以我只是为了完整起见才提到它。
现在有一个非常特殊的情况:您甚至可以在单个特征方法的中间使用类似 resetBrowser(); CachingDriverFactory.clearCacheAndQuitDriver()
的东西,如下所示:
package de.scrum_master.testing
import geb.driver.CachingDriverFactory
import geb.spock.GebReportingSpec
class RestartBrowserIT extends GebReportingSpec {
def "Search web site Scrum-Master.de"() {
when:_ "download page is opened"
go "https://scrum-master.de"
report "welcome page"
then:_ "expected text is found on page"
$("h2").text().startsWith("Herzlich Willkommen bei Scrum-Master.de")
when:_ "browser is reset"
resetBrowser()
CachingDriverFactory.clearCacheAndQuitDriver()
and:_ "download page is opened again in new browser"
go "https://scrum-master.de/Downloads"
report "download page"
then:_ "expected text is found on page"
$("h2").text().startsWith("Scrum on a Page")
}
}
然后在控制台上你会看到类似这样的东西:
download page is opened
07:49:49.105 [main] INFO i.g.bonigarcia.wdm.WebDriverManager - Using chromedriver 83.0.4103.39 (since Google Chrome 83 is installed in your machine)
07:49:49.146 [main] INFO i.g.bonigarcia.wdm.WebDriverManager - Exporting webdriver.chrome.driver as C:\Users\alexa\.m2\repository\webdriver\chromedriver\win32.0.4103.39\chromedriver.exe
Starting ChromeDriver 83.0.4103.39 (ccbf011cb2d2b19b506d844400483861342c20cd-refs/branch-heads/4103@{#416}) on port 3302
Only local connections are allowed.
Please see https://chromedriver.chromium.org/security-considerations for suggestions on keeping ChromeDriver safe.
ChromeDriver was started successfully.
Jul 03, 2020 7:49:53 AM org.openqa.selenium.remote.ProtocolHandshake createSession
INFORMATION: Detected dialect: W3C
expected text is found on page
browser is reset
download page is opened again in new browser
07:49:57.387 [main] INFO i.g.bonigarcia.wdm.WebDriverManager - Using chromedriver 83.0.4103.39 (since Google Chrome 83 is installed in your machine)
07:49:57.413 [main] INFO i.g.bonigarcia.wdm.WebDriverManager - Exporting webdriver.chrome.driver as C:\Users\alexa\.m2\repository\webdriver\chromedriver\win32.0.4103.39\chromedriver.exe
Starting ChromeDriver 83.0.4103.39 (ccbf011cb2d2b19b506d844400483861342c20cd-refs/branch-heads/4103@{#416}) on port 27426
Only local connections are allowed.
Please see https://chromedriver.chromium.org/security-considerations for suggestions on keeping ChromeDriver safe.
ChromeDriver was started successfully.
Jul 03, 2020 7:50:00 AM org.openqa.selenium.remote.ProtocolHandshake createSession
INFORMATION: Detected dialect: W3C
expected text is found on page
P.S.: 以防万一你想知道为什么我写 when:_ "label"
而不是 when: "label"
,我使用这个 SpockConfig.groovy
文件来帮助我打印我测试中的标签,您也可以在上面的控制台日志中看到:
import spock.lang.Specification
/**
* Use like this in order to print Spock/Geb labels:
* given:_ "foo"
* when:_ "bar"
* then:_ "zot"
*/
class LabelPrinter {
def _(def message) {
println message
true
}
}
Specification.mixin LabelPrinter
如果您使用标准的 Maven 目录布局,Spock 配置文件应该在 src/main/resources/SpockConfig.groovy
中。
我从一个旧项目中导入了一个 class 名为“TestGebSpec”的项目。它的测试用例是 运行ning 在同一个浏览器上,所以我在 gebConfig.groovy 文件中添加了一个“CachingDriverFactory.clearCacheAndQuitDriver()”。不过,测试用例 运行 在同一个浏览器上运行,所以我创建了一个新的 groovy 测试用例文件“Login TC”
现在的问题是登录 TC 的测试用例 运行 在单独的浏览器上运行,即对于每个测试用例,都会启动一个新的驱动程序,但对于文件“TestGebSpec”,不知何故 TC 运行s在同一个浏览器上
有什么建议吗???
“TestGebSpec”文件的代码
@Stepwise
@SuppressWarnings(["GrUnresolvedAccess", "GroovyAssignabilityCheck", "UnnecessaryQualifiedReference"])
class KohlerSanityTestGebSpec extends GebReportingSpec {
public static final String USER_EMAIL = "test_user." + UUID.randomUUID() + "@kohler.com"
public static final String USER_PASSWORD = "pass123Word"
@Shared
productAddedToFolder
def setupSpec() {
driver.manage().window().maximize()
}
def setup() {}
def cleanup() {}
def cleanupSpec() {}
//--------------------------------------------------------------
// Utility methods start here.
//--------------------------------------------------------------
/** Using javascript runner to scroll an element into view so selenium can work with it. */
protected void scrollIntoViewJS(NonEmptyNavigator element) {
((JavascriptExecutor) driver).executeScript(
"arguments[0].scrollIntoView(true);",
element.firstElement());
sleep(1000)
}
protected void scrollUp(int distance) {
((JavascriptExecutor) driver).executeScript("scroll( 0, ${-distance});");
sleep(100)
}
protected void scrollDown(int distance) {
((JavascriptExecutor) driver).executeScript("scroll( 0, ${distance});");
sleep(100)
}
protected void hoverTest2(NonEmptyNavigator element) {
((JavascriptExecutor) driver).executeScript(
"arguments[0].trigger(\"hover\");",
element.firstElement());
}
protected void hoverOver(String path) {
org.openqa.selenium.WebElement element =
driver.findElement(org.openqa.selenium.By.cssSelector(path))
hoverOver(element)
}
protected void hoverOver(NonEmptyNavigator element) {
org.openqa.selenium.interactions.Actions builder = new
org.openqa.selenium.interactions.Actions(driver)
builder.moveToElement(element.getElement(0)).build().perform()
}
/** click, when the click() method does not work. */
@SuppressWarnings("GroovyUnusedDeclaration")
protected void clickElement(NonEmptyNavigator element) {
org.openqa.selenium.interactions.Actions builder = new org.openqa.selenium.interactions.Actions(driver)
builder.moveToElement(element.getElement(0)).click().build().perform()
}
protected void moveElement(NonEmptyNavigator handleElement, NonEmptyNavigator trackElement, int xPercent) {
org.openqa.selenium.WebElement handle = handleElement.getElement(0)
org.openqa.selenium.WebElement track = trackElement.getElement(0)
org.openqa.selenium.interactions.Actions builder = new org.openqa.selenium.interactions.Actions(driver)
int width = track.getSize().getWidth()
int moveLength = width * xPercent / 100
builder.dragAndDropBy(handle as org.openqa.selenium.WebElement, moveLength.intValue(), (int) 0).build().perform()
}
protected void closeSurveyPopup() {
if ($("#IPEbgCover")) {
$("area", alt: "close").click()
}
}
//----------------------------------------------------------------
// End of utility methods. Start of feature methods.
//----------------------------------------------------------------
def "Create project in bCC TESTCASE1"() {
browser.baseUrl = "URL"
when: "I log in to the BCC"
to BccLoginPage
loginForm.login = "data"
loginForm.$("#loginPassword").value("data")
$("input", type: "submit").click()
then:
at BccHomePage
when:
newCaProjectButton.click()
then:
at BccNewCaProject01Page
when: "I name and describe the new project."
def newProjectName = "gebtest-" + randomString(16, ('A'..'Z') + ('0'..'9'))
println "Creating BCC project \"$newProjectName\"."
projectNameInput.value(newProjectName)
projectDescriptionInput.value(randomString(50))
createProcessButton.click()
then:
at BccCaProjectDetailsPage
}
}
“登录TC”文件代码
class LoginTC extends GebReportingSpec{
def setupSpec() {
driver.manage().window().maximize()
//driver.manage().window().size = new org.openqa.selenium.Dimension( 1200, 1200 )
} // run before the first feature method
def setup() {} // run before every feature method
def cleanup() {} // run after every feature method
def cleanupSpec() {} // run after the last feature method
void "login tc2"(){
setup:
to HomePage
final String searchString = "string data"
searchInput = searchString
when:
btnSearch.click()
then:
at waitFor{ ProductDetailPage }
and:
sku.text().toLowerCase().contains( searchString.toLowerCase() )
}
void "login tc3"(){
setup:
to HomePage
final String searchString = "string data"
searchInput = searchString
when:
btnSearch.click()
then:
at waitFor{ ProductDetailPage }
}
}
简而言之,问题是为什么“TestGebSpec”文件 运行s 在同一浏览器上的功能
流程如下
1.Open 浏览器
2.Feature 1 运行
3.Feature 2 运行
.
.
.
最后一点。浏览器关闭
我除外
1.open 浏览器
2.Feature 1 运行
3.Close 浏览器
4.Open 浏览器
5.Feature 2 运行
6.Close 浏览器
实际上,如果下一个功能需要重新打开初始 URL,您网页上的错误应该不是问题。此外,cookie 应该不是问题,因为您可以手动或自动删除它们。过度使用 @Stepwise
也是许多用户问题的根源。你应该尽可能避免它。我什至看到您在只有一项功能的规范中使用它(或者您可能只向我展示了一项,但实际上还有更多)。使用许多浏览器是一种巨大的资源浪费,只会让你的测试变慢。 Geb 之书(手册)是极好的信息来源。
看看 implicit lifecycle with regard to clearCookies()
andclearWebStorage()
. Auto-clearing cookies and/or web storage 可能也会有所帮助。同一章还解释说,如果您只是在功能方法的末尾使用 CachingDriverFactory.clearCacheAndQuitDriver()
(或者如果您在每个功能中都需要它,则在 cleanup()
中),下一个方法将自动获取一个新的浏览器实例。
当然你可以quit the browser通过quit()
(退出浏览器)和close()
(关闭当前浏览器window)如果你想手动启动新浏览器.但是隐式驱动程序管理更容易使用 IMO,所以我只是为了完整起见才提到它。
现在有一个非常特殊的情况:您甚至可以在单个特征方法的中间使用类似 resetBrowser(); CachingDriverFactory.clearCacheAndQuitDriver()
的东西,如下所示:
package de.scrum_master.testing
import geb.driver.CachingDriverFactory
import geb.spock.GebReportingSpec
class RestartBrowserIT extends GebReportingSpec {
def "Search web site Scrum-Master.de"() {
when:_ "download page is opened"
go "https://scrum-master.de"
report "welcome page"
then:_ "expected text is found on page"
$("h2").text().startsWith("Herzlich Willkommen bei Scrum-Master.de")
when:_ "browser is reset"
resetBrowser()
CachingDriverFactory.clearCacheAndQuitDriver()
and:_ "download page is opened again in new browser"
go "https://scrum-master.de/Downloads"
report "download page"
then:_ "expected text is found on page"
$("h2").text().startsWith("Scrum on a Page")
}
}
然后在控制台上你会看到类似这样的东西:
download page is opened
07:49:49.105 [main] INFO i.g.bonigarcia.wdm.WebDriverManager - Using chromedriver 83.0.4103.39 (since Google Chrome 83 is installed in your machine)
07:49:49.146 [main] INFO i.g.bonigarcia.wdm.WebDriverManager - Exporting webdriver.chrome.driver as C:\Users\alexa\.m2\repository\webdriver\chromedriver\win32.0.4103.39\chromedriver.exe
Starting ChromeDriver 83.0.4103.39 (ccbf011cb2d2b19b506d844400483861342c20cd-refs/branch-heads/4103@{#416}) on port 3302
Only local connections are allowed.
Please see https://chromedriver.chromium.org/security-considerations for suggestions on keeping ChromeDriver safe.
ChromeDriver was started successfully.
Jul 03, 2020 7:49:53 AM org.openqa.selenium.remote.ProtocolHandshake createSession
INFORMATION: Detected dialect: W3C
expected text is found on page
browser is reset
download page is opened again in new browser
07:49:57.387 [main] INFO i.g.bonigarcia.wdm.WebDriverManager - Using chromedriver 83.0.4103.39 (since Google Chrome 83 is installed in your machine)
07:49:57.413 [main] INFO i.g.bonigarcia.wdm.WebDriverManager - Exporting webdriver.chrome.driver as C:\Users\alexa\.m2\repository\webdriver\chromedriver\win32.0.4103.39\chromedriver.exe
Starting ChromeDriver 83.0.4103.39 (ccbf011cb2d2b19b506d844400483861342c20cd-refs/branch-heads/4103@{#416}) on port 27426
Only local connections are allowed.
Please see https://chromedriver.chromium.org/security-considerations for suggestions on keeping ChromeDriver safe.
ChromeDriver was started successfully.
Jul 03, 2020 7:50:00 AM org.openqa.selenium.remote.ProtocolHandshake createSession
INFORMATION: Detected dialect: W3C
expected text is found on page
P.S.: 以防万一你想知道为什么我写 when:_ "label"
而不是 when: "label"
,我使用这个 SpockConfig.groovy
文件来帮助我打印我测试中的标签,您也可以在上面的控制台日志中看到:
import spock.lang.Specification
/**
* Use like this in order to print Spock/Geb labels:
* given:_ "foo"
* when:_ "bar"
* then:_ "zot"
*/
class LabelPrinter {
def _(def message) {
println message
true
}
}
Specification.mixin LabelPrinter
如果您使用标准的 Maven 目录布局,Spock 配置文件应该在 src/main/resources/SpockConfig.groovy
中。