最近接到一个项目调研,是要爬取一个第三方站点的表单数据; 先经历密码登录验证的动作(不需要验证码), 然后会看到一个表单,获取上面的元素;
虽然这个项目很简单,但是突然想到了这个需求本质上也可以理解成一个网站自动测试的过程; 输入站点 --> 输入用户名/密码 --> 获取/验证表单信息;
好久没关注这相关内容,然后就简单看一下目前市场上流程的web 自动测试流程的框架; 发现了selenium openQA, 并简单试玩了一下,比我想象中简单许多,有编程基础的人,熟悉一下API就可非常轻易的上手;
- Chrome 插件 Selenium IDE;可以将其理解为一个在网站动作的宏(记录仪),可以回放;
- 看到这一堆指令,我猜想,应该有某种可以导出为代码的功能吧?简单google还真有,我在百度上随便点击几下,输入几个关键字所记录下的宏转成Java代码如下代码附录;
- 虽然看起来很简单,但是Selenium openQA应该只能做一些简单的数据合法性的检验,对于一些前端页面复杂的显示效果的检验,应该很困难吧;
- 似乎写这种测试用例也难有模式,拓展性可言,因为毕竟都是被动去应付各种需求,不确定如何变动?
- 有一个很重要的场景就是,就是会同时运行连接同一个DB的两个版本的Web Program, 对比两个页面的screenshot,以测试更新前后是否会对业务元素产生影响;
- selenium ide 似乎此前有过相关功能,但是在最新的版本中将其移除; 细节可以参考 讨论 https://github.com/SeleniumHQ/selenium-ide/issues/182 anyway, 自己coding代码应该不受影响(调用webdriver API);
- 获得2个图片以后,需要对其进行对比, selenium并没有提供任何官方的功能;这个相关的工具很多,提供两个SIKULIX
和 romankh3
// Generated by Selenium IDE
import org.junit.Test;
import org.junit.Before;
import org.junit.After;
import static org.junit.Assert.*;
import static org.hamcrest.CoreMatchers.is;
import static org.hamcrest.core.IsNot.not;
import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.firefox.FirefoxDriver;
import org.openqa.selenium.chrome.ChromeDriver;
import org.openqa.selenium.remote.RemoteWebDriver;
import org.openqa.selenium.remote.DesiredCapabilities;
import org.openqa.selenium.Dimension;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.interactions.Actions;
import org.openqa.selenium.support.ui.ExpectedConditions;
import org.openqa.selenium.support.ui.WebDriverWait;
import org.openqa.selenium.JavascriptExecutor;
import org.openqa.selenium.Alert;
import org.openqa.selenium.Keys;
import java.util.*;
import java.net.MalformedURLException;
import java.net.URL;
public class Test {
private WebDriver driver;
private Map<String, Object> vars;
JavascriptExecutor js;
@Before
public void setUp() {
driver = new ChromeDriver();
js = (JavascriptExecutor) driver;
vars = new HashMap<String, Object>();
}
@After
public void tearDown() {
driver.quit();
}
public String waitForWindow(int timeout) {
try {
Thread.sleep(timeout);
} catch (InterruptedException e) {
e.printStackTrace();
}
Set<String> whNow = driver.getWindowHandles();
Set<String> whThen = (Set<String>) vars.get("window_handles");
if (whNow.size() > whThen.size()) {
whNow.removeAll(whThen);
}
return whNow.iterator().next();
}
@Test
public void () {
driver.get("https://www.baidu.com/");
driver.manage().window().setSize(new Dimension(1390, 1020));
driver.findElement(By.id("kw")).sendKeys("我时谁");
driver.findElement(By.id("kw")).sendKeys(Keys.ENTER);
{
WebElement element = driver.findElement(By.linkText("设置"));
Actions builder = new Actions(driver);
builder.moveToElement(element).perform();
}
{
WebElement element = driver.findElement(By.tagName("body"));
Actions builder = new Actions(driver);
builder.moveToElement(element, 0, 0).perform();
}
vars.put("window_handles", driver.getWindowHandles());
driver.findElement(By.linkText("未生我时谁是我,生我之时我是谁?这句话出自哪里?_百度知道")).click();
vars.put("win6254", waitForWindow(2000));
driver.switchTo().window(vars.get("win6254").toString());
{
WebElement element = driver.findElement(By.cssSelector(".item img"));
Actions builder = new Actions(driver);
builder.moveToElement(element).perform();
}
{
WebElement element = driver.findElement(By.tagName("body"));
Actions builder = new Actions(driver);
builder.moveToElement(element, 0, 0).perform();
}
js.executeScript("window.scrollTo(0,0)");
vars.put("window_handles", driver.getWindowHandles());
driver.findElement(By.cssSelector("#answer-content-591358604 > .baidu-highlight")).click();
vars.put("win7027", waitForWindow(2000));
driver.switchTo().window(vars.get("win7027").toString());
{
String value = driver.findElement(By.id("kw")).getAttribute("value");
assertThat(value, is("顺治皇帝"));
}
}
}