使用 where 子句在 GEB cookie 中进行 Spock 测试

Spock test in GEB cookies using where clause

我已经配置了一些 geb 测试来检查不同的消息,具体取决于我的网络应用程序中的登录尝试。由于消息和输入字段将在第三次尝试登录时更改。

登录是基于发送到特定 phone 号码的密码的两步登录,因此在第一页 LoginPage 用户介绍他们的 IdphoneNumber,然后重定向到第二个页面ValidationLoginPage,用户介绍收到的密码.

我想检查一下,在第二页中,用户只能输入三个错误的密码,在第四次尝试输入密码时,输入密码的输入将会消失,并且会显示一条不同的消息,表明不再显示它的尝试。

为了检查这一点,我准备了一个测试,它在 given: 处引入了 IdphoneNumber子句,并使用 where: 子句,它引入了三次错误密码。由于 where: 重复所有测试,我尝试控制部分重复使用注入变量,如 where: 中,所以我有类似的东西:

def "Test max loging attempts"(){
  given:
    if(loginAttempt == 1)
      to LoginPage
      loginModule.startLogin(cfg.user.id,cfg.user.phone)
    }
  when:
    at LoginValidationPage
    assert  $('div.box_id_header h3').text() == 'Verify your code'
    assert  $('#code').css('display').contains('block')
    loginModule.verifyPassword('WRONGPASSWORD')
  then:
    at LoginValidationPage
    println "Attempt ${loginAttempt}"
    if(loginAttempt == 4){
      // last attempt
      assert    $('#code').css('display') == 'none' 
      assert  $('#divCodeErrorMsg').text().contains('No more attempts')
    }else{
      assert    $('#code').css('display').contains('block')
      assert  $('#divCodeErrorMsg').text().contains('Wrong password. Try again.')
    }
  where:            
    loginAttempt << (1..4)
}

我的问题是,每次 where: 迭代都会清除 cookies,认为消息和行为不是我所期望的。我不想在 GebConfig.groovy 文件中配置 autoClearCookies=false,因为我有另一个需要此功能的测试。有一种方法可以使用 spock def setupSpec() {} 方法避免清除此方法的 cookie,并在 def cleanupSpec() {} 方法中重新激活?

此外,还可以更简洁地使用 where:,避免检查 loginAttempt 变量以避免多次 运行 given: 部分,或者有一个根本不使用 where: 的更好方法?

最终在 setup 步骤中禁用 autoClearCookies 我得到了想要的行为。

def setup() {
    browser.getConfig().setAutoClearCookies(false)      
}

然而令人惊讶的是,如果我使用 setupSpec() 方法,似乎它不起作用,因为只有第一个 where: 迭代有 autoClearCookies=false,其余的有 autoClearCookies=true.

问题是您可能误解并因此滥用了 Spock 的 where: 块。它旨在对特征方法进行参数化,并且该方法的每个 运行 都包含一个独立的特征。如果您 @Unroll 您的功能,即使对于每组 where: 参数,也会生成一个新方法。因为功能应该相互独立并且理论上能够 运行 运行 以任何给定的顺序甚至并行,所以需要重置测试夹具才能 运行 它们。这就是您的 cookie 发生的情况,因为您滥用 where: 功能来实现一个简单的循环。

您的代码中还有其他小问题,例如 when: 块中未声明的 at 检查。即使 at 产生 false,如果您不使用 assert,它也没有任何影响。您只能在 then:expect: 块中跳过 assert,但不能在 given:when: 中跳过,也不能在我将同时使用的闭包或辅助方法中跳过在我的示例代码中。

这个怎么样?

package de.scrum_master.Whosebug.foo

import geb.spock.GebReportingSpec

class LoginTest extends GebReportingSpec {
  def loginModule = new LoginModule()
  def cfg = new Config()

  def "Test max login attempts"() {
    given: "we are at the login page"
    browser.config.autoClearCookies = false
    to LoginPage

    when: "logging in 4x with wrong credentials"
    (1..4).each {
      loginWithWrongCredentials(it, it < 4)
    }

    then: "we get a 'no more attempts' error message"
    $('#codi').css('display') == 'none'
    $('#divCodiValidacioError').text().contains('No more attempts')
  }

  def loginWithWrongCredentials(int loginAttempt, boolean checkForWrongPasswordMessage) {
    println "Login attempt ${loginAttempt}"
    loginModule.startLogin(cfg.user.id, cfg.user.phone)
    assert at(LoginValidationPage)
    assert $('div.box_id_header h3').text() == 'Verify your code'
    assert $('#code').css('display').contains('block')
    loginModule.verifyPassword('WRONGPASSWORD')
    assert at(LoginValidationPage)
    if (checkForWrongPasswordMessage) {
      assert $('#codi').css('display').contains('block')
      assert $('#divCodiErrorMsg').text().contains('Wrong password. Try again.')
    }
  }
}

我还建议将内容断言从 loginWithWrongCredentials 移动到 LoginValidationPage 的辅助方法中,它们更应该属于这些方法,并从测试中调用它们。