我使用 Java 进行测试自动化。我一直在寻找一种体面的方法来处理这些登录弹出窗口,但找不到。最常见的答案是在 URL 中包含作为实际 URL 之前的前缀(例如 https:\username:password@www.website.com)或使用等待警报。这些对我没有用,因为:在提交表单时没有简单的 url 可以使用,我不确定安全性,包括 url 开头的密码;随着等待警报,webdriver 会挂起,直到有响应 - 这仅来自通过弹出窗口提交登录响应。
我发现的解决方法很差 - 我没有让它在无头环境中工作,因此限制了这个答案的有用性。在这里得到一个真正的答案会很棒。请注意,我在 Windows 环境中运行它,如果我使用的是 Linux,我已经读过我可以使用 xvfb 为 sikuli 提供“屏幕”,然后这将起作用 - 如果有人可以评论如何在 Windows 上执行此操作非常感谢的服务器。
我使用 Sikuli 来自动化我无法通过 Selenium 自动化的事情。 Sikuli 做了很多事情,包括让你基本上向它提供图像,它会在上面执行操作。
为此,我在单击提交导致登录弹出窗口之前启动的线程上运行 Sikuli。由于它在不同的线程上运行,它不会阻塞主线程,因此它仍然可以执行登录。一旦它登录,它就会关闭并登录关闭弹出窗口并重新激活主线程。
具体来说:
用于 POM 的 Sikuli MAVEN 条目:
<dependency>
<groupId>com.sikulix</groupId>
<artifactId>sikulixapi</artifactId>
<version>1.1.4-20191010.160947-268</version>
</dependency>
在主代码中使用通过 executor 执行的 runnable:
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
private final AtomicInteger expectedResultCount;
private final AtomicInteger publishedResultCount;
private final ExecutorService executor;
ExecutorService executor = Executors.newFixedThreadPool(5);
String processName = "asic-login";
LoginPopUp login = new LoginPopUp(this, processName);
addResultExpectation(processName);
executor.execute(login);
这里的runnable实现了一个我用来保持整洁的接口:
主类实现了管理线程的接口:
public class TestRunner implements ResultPublisher{
这些是主类中用于线程管理的函数:
private void addResultExpectation(String process){
resultMap.put(process, new JSONObject());
expectedResultCount.addAndGet(1);
}
public void publishResult(JSONObject result){
String process = result.getString("process-name");
String strResult = result.getString("result");
resultMap.put(process, result);
publishedResultCount.addAndGet(1);
if(publishedResultCount.get() == expectedResultCount.get()){
executor.shutdown();
System.out.println("shutting down executor for run " + runId);
}
}
这是界面
import org.json.JSONObject;
public interface ResultPublisher {
void publishResult(JSONObject result);
}
这是可运行的Runnable——TestRunner主类中的一个内部类:
private class LoginPopUp implements Runnable{
private ResultPublisher publisher;
private String filePath;
private String processName;
private LoginPopUp(){
}
public LoginPopUp(ResultPublisher publisher, String processName){
this.publisher = publisher;
this.processName = processName;
}
private void publish(JSONObject result){
publisher.publishResult(result);
}
public void run(){
JSONObject result = new JSONObject();
result.put("path", filePath);
try{
Screen sd = new Screen();
ScreenUtility s = new ScreenUtility(imagesDirectory);
s.clickImage("LoginTitle.PNG", 10, 2500);
s.typeImageWithOffset("UserName.PNG", userName, 30,0);
s.typeImageWithOffset("Password.PNG",String.valueOf(password), 50,0);
s.clickImage("AsicSignIn.PNG", 10, 250);
}catch(Exception ex){
result.put("result", ex.getMessage());
result.put("process-name", processName);
publish(result);
Logger.getLogger(BCSRobot.class.getName()).log(Level.SEVERE, null, ex);
return;
}
result.put("result", "logged in successfully");
result.put("process-name", processName);
publish(result);
return;
}
}