0

这可能类似于5660956,但我先做一个 GET ......

我认为这里的关键是 Selenium,因此是标签。以防万一:我正在使用 Java,使用 NinjaFramewor、FluentLenium 和 Firefox。它在本地运行,也可以在带有 Xvfb 的无头 CI 盒上运行。我通过了一些 FluentLenium 测试,所以整个事情都没有坏掉!

我有一个网页,带有一个简单的登录表单,该表单执行对执行 AJAX POST 的 JavaScript 的调用。AJAX 响应被 JavaScript 捕获并导致页面的某些主体更新,登录、注册和失败的结果不同。当我手动测试时,甚至当我在本地运行这些测试时,我都可以看到这种情况。

测试看起来像这样:

import org.fluentlenium.adapter.util.SharedDriver;
import org.fluentlenium.core.annotation.Page;
import org.junit.Test;

@SharedDriver(deleteCookies=true)
public class UserControllerTest extends JSTest {

  @Page
  HomePage home;
  @Page 
  LoginPage login;

  @Test
  public void test_cantLoginUntilReg() {
    goTo(login);
    login.fillOutReg("test_cantLoginUntilReg");
    login.chooseLogin();    // script that POSTS and does AJAX update
    login.isErrorResult();  // errors
    goTo(login);
    login.fillOutReg("test_cantLoginUntilReg");
    login.chooseRegister();   // script that POSTS and does AJAX update
    login.isWelcomeResult();  // errors
    login.chooseHome();       // GET on home
    home.isLoggedIn();        // this works
}

// more tests
}

而我遇到麻烦的 LoginPage 看起来像(包含一个包含常量的超类):

public class LoginPage extends FluentPage {

  protected static final String HOME_PAGE = "http://localhost:8080";
  private static final String PAGE = HOME_PAGE + "/login";

  @AjaxElement
  FluentWebElement welcomeDiv;
  @AjaxElement
  FluentWebElement errorDiv;

  @Override
  public String getUrl() {
    return PAGE;
  }

  @Override
  public void isAt() {
    assertTrue("url is " + url(), url().contains("login"));
    assertTrue("h1 is " + find("h1").getText(), find("h1").getText().contains("Login"));
    assertTrue("h1 is " + find("h1").getText(), find("h1").getText().contains("Register"));
  }

  public void isErrorResult() {
   assertTrue("h1 is " + find("h1").getText(), find("h1").getText().contains("Failed"));
   assertNull("cookie is " + getCookie(SESSION_COOKIE_NAME), getCookie(SESSION_COOKIE_NAME));
 }

  public void fillOutReg(String testName) {
    fill("#email").with(testName + "@UserControllerJSTests.test.com"); // this passes the minimal validation in place so far
    fill("#password").with("reallyBadPassword");
    fill("#identName").with(testName);  
  }

  public void chooseLogin() {
    executeScript(LOGIN_SCRIPT); // I'd prefer click on the form, but that seemed to be a source of trouble as well
  }

// and so on
}

isErrorResult() 方法永远不会满足!查找 h1 显示 h1 文本仍然与第一次加载页面时一样。清除会话 cookie 会在不同的机器上显示不同的行为(可能需要等待某些东西)。我也试过测试welcomeDiv 的内容。我觉得我应该能够在这里使用@AjaxElement 来提供帮助,但我还没有完全弄清楚如何做。

我不想检查返回的 JSON。我已经进行了不涉及 Selenium 的测试,这些测试已经非常接近了。

我想要做的是自动检查用户是否会在 POST 后在浏览器端看到正确的内容。即使有这个代码的变通方法,其他功能也会有足够大的上传,GET 真的是不明智的;可测试的 AJAX 似乎是一种合理的需求。

请问有什么想法吗?

4

1 回答 1

0

我有一个可行的解决方案。与以往一样,变化的组合让我到达了我想去的地方。按照重要性的粗略顺序,我认为它们是:

  • 在任何给定的测试中只查询一次@Page 的状态。Ajaxed 内容的第一次测试获胜。随后的那些发现了错误的值。
  • 进行断言调用以测试 ajax 元素是否应该来自测试对象而不是页面对象。损坏的版本在下面的代码中被注释掉,因为这是出乎意料的。
  • 使用 @AjaxElement 然后查询这些元素的内容。
  • 一个网页在我正在寻找的元素上缺少 id 标签(不会解决所有问题)。
  • 除了其他一些小变化之外,我现在正在测试标题 h1 元素和列表元素,而不是包含它们的 div;并且不同版本的h1有不同的id值。还没有(还)回归检查这是多么重要。

现在的测试代码是:

import org.fluentlenium.adapter.util.SharedDriver;
import org.fluentlenium.core.annotation.Page; 
import static org.junit.Assert.assertTrue;
import org.junit.Test;

@SharedDriver(deleteCookies=true)
public class UserControllerTest extends JSTest {

 @Page
 HomePage home;
 @Page 
 LoginPage login;

 @Test
 public void test_cantLoginBeforeReg() {
    // try to login without being registered
    goTo(login);
    login.fillOutReg("test_cantLoginUntilReg");
    login.chooseLogin();
    isErrorResult();
    goTo(home);
    home.isNotLoggedIn();
 }

 @Test
 public void test_registerLogout() {
    goTo(login);
    login.fillOutReg("test_registerLogout");
    login.chooseRegister();
    isWelcomeResult();
    login.chooseLogout();
    home.isAt();
    home.isNotLoggedIn();
 }

// tests etc

 public void isWelcomeResult() {
    assertTrue(login.getWelcomeText(), login.getWelcomeText().contains("Welcome"));
 }
 public void isErrorResult() {
    assertTrue(login.getErrorText(), login.getErrorText().contains("Failed"));
 }
}

和页面类:

import org.fluentlenium.core.annotation.AjaxElement;
import org.fluentlenium.core.domain.FluentWebElement;
import static org.junit.Assert.assertTrue;

public class LoginPage extends TripVisPage {

private static final String PAGE = HOME_PAGE + "/login";

@AjaxElement
FluentWebElement welcomeHeading;
@AjaxElement
FluentWebElement errorHeading;

@Override
public String getUrl() {
  return PAGE;
}

public String getWelcomeText() {
  return welcomeHeading.getText();
}

public String getErrorText() {
  return errorHeading.getText();
}

@Override
public void isAt() {
  assertTrue("url is " + url(), url().contains("login"));
  assertTrue("h1 is " + find("h1").getText(), find("h1").getText().contains("Login"));
  assertTrue("h1 is " + find("h1").getText(), find("h1").getText().contains("Register"));
}
/* calling these from the test is broken
public void isWelcomeResult() {
  assertTrue(getWelcomeText(), getWelcomeText().contains("Welcome"));
}
public void isErrorResult() {
  assertTrue(getErrorText(), getErrorText().contains("Failed"));
}
*/
public void fillOutReg(String testName) {
  fill("#email").with(testName + "@UserControllerJSTests.tripvis.co.uk");
  fill("#password").with("reallyBadPassword");
  fill("#identName").with(testName);    
}

public void chooseAbout() {
  click(LINK_ABOUT_ID);
}

public void chooseLegal() {
  click(LINK_LEGAL_ID);
}

public void chooseRegister() {
  executeScript(REGISTER_SCRIPT);
}

public void chooseLogin() {
  executeScript(LOGIN_SCRIPT);
}

public void chooseLogout() {
  click(LINK_LOGOUT_ID);
}
}
于 2014-11-05T14:49:53.140 回答