selenium
https://www.selenium.dev/documentation/zh-cn/selenium_installation/installing_selenium_libraries/
https://www.selenium.dev/documentation/en/selenium_installation/installing_selenium_libraries/
安装
安装client
https://www.selenium.dev/documentation/en/selenium_installation/installing_selenium_libraries/
安装driver
Browser | Supported OS | Maintained by | Download | Issue Tracker |
---|---|---|---|---|
Chromium/Chrome | Windows/macOS/Linux | Downloads | Issues | |
Firefox | Windows/macOS/Linux | Mozilla | Downloads | Issues |
Edge | Windows 10 | Microsoft | Downloads | Issues |
Internet Explorer | Windows | Selenium Project | Downloads | Issues |
Safari | macOS El Capitan and newer | Apple | Built in | Issues |
Opera | Windows/macOS/Linux | Opera | Downloads | Issues |
seveniruby:web seveniruby$ which chromedriver
/Users/seveniruby/ke/java_4/web//chromedriver
seveniruby:web seveniruby$ chromedriver -v
ChromeDriver 86.0.4240.22 (398b0743353ff36fb1b82468f63a3a93b4e2e89e-refs/branch-heads/4240@{#378})
可选的,安装selenium server
https://www.selenium.dev/documentation/en/selenium_installation/installing_standalone_server/
定位
https://www.w3schools.com/cssref/css_selectors.asp
定位技巧
#css定位
$('.search-dropdown .d-icon-search')
#xpath定位
$x('//*[@title="搜索主题、帖子、用户或分类"]')
selenium IDE
自动录制生成的代码模板
// 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 UntitledTest {
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();
}
@Test
public void untitled() {
driver.get("https://ceshiren.com/");
driver.manage().window().setSize(new Dimension(1440, 822));
driver.findElement(By.cssSelector(".d-icon-search")).click();
{
WebElement element = driver.findElement(By.cssSelector(".d-icon-search"));
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();
}
driver.findElement(By.id("search-term")).click();
driver.findElement(By.id("search-term")).sendKeys("selenium");
driver.findElement(By.id("search-term")).sendKeys(Keys.ENTER);
{
WebElement element = driver.findElement(By.cssSelector("li:nth-child(3) > a > 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();
}
driver.findElement(By.id("ember499")).click();
driver.findElement(By.id("ember499")).click();
}
}
显式等待与隐式等待
- 客户端等待 vs 服务端等待
- 间隔时间,等待条件可以灵活控制 VS 除了整体的等待时间其他无法控制
- 可以等待控件小时 VS 很难实现等待控件消失
关键参数的区别
- 显式等待(超时时间、间隔时间、执行过程)
- 隐式等待(超时时间、间隔时间不可修改、find_element不可修改)
/**
* Repeatedly applies this instance's input value to the given function until one of the following
* occurs:
* <ol>
* <li>the function returns neither null nor false</li>
* <li>the function throws an unignored exception</li>
* <li>the timeout expires</li>
* <li>the current thread is interrupted</li>
* </ol>
*
* @param isTrue the parameter to pass to the {@link ExpectedCondition}
* @param <V> The function's expected return type.
* @return The function's return value if the function returned something different
* from null or false before the timeout expired.
* @throws TimeoutException If the timeout expires.
*/
@Override
public <V> V until(Function<? super T, V> isTrue) {
Instant end = clock.instant().plus(timeout);
Throwable lastException;
while (true) {
try {
V value = isTrue.apply(input);
if (value != null && (Boolean.class != value.getClass() || Boolean.TRUE.equals(value))) {
return value;
}
// Clear the last exception; if another retry or timeout exception would
// be caused by a false or null value, the last exception is not the
// cause of the timeout.
lastException = null;
} catch (Throwable e) {
lastException = propagateIfNotIgnored(e);
}
// Check the timeout after evaluating the function to ensure conditions
// with a zero timeout can succeed.
if (end.isBefore(clock.instant())) {
String message = messageSupplier != null ?
messageSupplier.get() : null;
String timeoutMessage = String.format(
"Expected condition failed: %s (tried for %d second(s) with %d milliseconds interval)",
message == null ? "waiting for " + isTrue : message,
timeout.getSeconds(), interval.toMillis());
throw timeoutException(timeoutMessage, lastException);
}
try {
sleeper.sleep(interval);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
throw new WebDriverException(e);
}
}
}
常见认证自动化问题
Yaml格式或者json格式的序列化与反序列化
https://github.com/FasterXML/jackson-dataformats-text/tree/master/yaml
企业微信扫码用cookie登录实践
演练代码
https://github.com/ceshiren/HogwartsJava4
课后作业
- 自动登录企业微信
- 添加成员自动化测试
把代码的git地址贴到回复里,码云或者github都可以