WebDriver中点击按钮、连接无效问题

本文探讨了WebDriver在测试过程中遇到的点击按钮和链接失效的问题,并提出了有效的解决方案。通过使用不同的方法如submit()和模拟键盘操作,成功地实现了自动化测试案例。
WebDriver中点击按钮、连接无效问题

 

之前在写一个测试用例的时候,就有发现点击提交按钮不起作用,今天又遇到点击链接也不起作用的情况。经过一些尝试,暂时已通过其他方式解决。

 

 

1.       软件版本

1)      操作系统:Win7 旗舰版(64位)

2)      JDK:1.7

3)      Eclipse:Mars Release (4.5.0) Eclipse Java EE IDE for Web Developers

4)      Eclipse TestNG插件:org.testng.eclipse_6.9.5.201506120235

5)      Webdriver:selenium-java-2.46.0

6)      IEDriverServer.exe

 

 

2.       被测对象说明

为了说明问题,我以一个简单的登陆流程作为测试对象:登陆页面,如果用户密码正确则提交后跳转到登陆成功页面,否则跳转到登陆失败页面,登陆失败页面有一个链接,点击后跳转到登陆界面。下面是各页面的代码。

 

2.1   登陆页面

点击(此处)折叠或打开

  1. <%@ page language="java"%>
  2. <%@ page language="java" contentType="text/html; charset=UTF-8"%>

  3. <% String path = request.getContextPath(); %>

  4. <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
  5. <html>
  6. <head>
  7. <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
  8. <title>系统登录</title>
  9. </head>
  10. <body>
  11.     <center>
  12.         <h1>系统登录</h1>
  13.         <hr>
  14.         <form name="loginForm" action="<%=path%>/login.action" method="post">
  15.             用户名:<input type="text" name="username" /><br>
  16.             密码:<input type="password" name="password" /><br>
  17.             <input type="submit" value="登录" id="btnLogin" name="btnLogin" /><br>
  18.         </form>
  19.     </center>
  20. </body>
  21. </html>


 

2.2   登陆成功页面

点击(此处)折叠或打开

  1. <%@ page language="java"%>
  2. <%@ page language="java" contentType="text/html; charset=UTF-8"%>
  3. <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
  4. <html>
  5. <head>
  6. <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
  7. <title>登录成功</title>
  8. </head>
  9. <body>
  10.     <center>
  11.         <h1>登录成功</h1>
  12.         <hr>        
  13.     </center>
  14. </body>
  15. </html>
 


2.3   登陆失败页面

点击(此处)折叠或打开

  1. <%@ page language="java" import="java.util.*"%>
  2. <%@ page language="java" contentType="text/html; charset=UTF-8"%>

  3. <% String path = request.getContextPath(); %>

  4. <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
  5. <html>
  6. <head>
  7. <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
  8. <title>登录失败</title>
  9. </head>
  10. <body>
  11.     <center>
  12.         <h1>登录失败</h1>
  13.         <hr>    
  14.         <a class="return" href="<%=path%>/login.jsp">返回</a>    
  15.     </center>
  16. </body>
  17. </html>


 

3.       点击提交按钮不起作用

一开始我针对登陆成功的测试用例是这样写的:

点击(此处)折叠或打开

  1. @Test
  2. public void loginSuccessTest() {
  3.         System.setProperty("webdriver.ie.driver", System.getProperty("user.dir")+"\\IEDriverServer.exe");
  4.         WebDriver driver = new InternetExplorerDriver();
  5.         driver.get("http://127.0.0.1:8080/ Login/");
  6.         driver.manage().window().maximize();
  7.         
  8.         CharSequence[] csUser = new CharSequence[1];
  9.         csUser[0] = "admin";
  10.         driver.findElement(By.name("username")).sendKeys(csUser);
  11.         
  12.         CharSequence[] csPW = new CharSequence[1];
  13.         csPW[0] = "123456";
  14.         driver.findElement(By.name("password")).sendKeys(csPW);
  15.         
  16.         driver.findElement(By.name("btnLogin ")).click();
  17.                 
  18.         String excepted = "登录成功";
  19.         String actual = driver.getTitle();
  20.         assertEquals(actual, excepted);
  21.         
  22.         driver.close();
  23.         
  24.         try{
  25.             Runtime.getRuntime().exec("tskill IEDriverServer");
  26.         }catch(IOException ie){
  27.             System.out.println("failed to close IEDriverServer......");
  28.             ie.printStackTrace();
  29.         }
  30. }


但执行这个用例,并没有点击【登录】按钮,执行到填写完两个文本输入框后就停止了,然后就关闭了,用例报错,说获取到的是【系统登录】而非期望的【登陆成功】。但没有报空指针异常,也就是说,submit按钮是获取到的,然后我又把click()改为submit(),即:

点击(此处)折叠或打开

  1. driver.findElement(By.name("btnLogin ")).submit ();


执行后还是一样一样的结果。

 

后来查到一篇关于click()和submit()区别的帖子[1],说click()只能用于submit按钮,而submit()可以用于form中的所有element,包括form本身。于是修改代码为:

点击(此处)折叠或打开

  1. driver.findElement(By.name("loginForm ")).submit ();


执行成功。

 

 

4.       点击链接不起作用

在测试失败页面点击【返回】连接跳转回登陆页面的用例中,又遇到点击后不起作用的问题。

点击(此处)折叠或打开

  1. @Test
  2. public void returnTest() {
  3.         System.setProperty("webdriver.ie.driver", System.getProperty("user.dir")+"\\IEDriverServer.exe");
  4.         driver = new InternetExplorerDriver();
  5.         driver.get("http://127.0.0.1:8080/Login/login_failure.jsp");
  6.         driver.manage().window().maximize();
  7.         
  8.         driver.findElement(By.xpath("//a[@class='return']")).click();

  9.         String excepted = "系统登录";
  10.         String actual = driver.getTitle();
  11.         assertEquals(actual, excepted);
  12.         
  13.         driver.close();
  14.         
  15.         try{
  16.             Runtime.getRuntime().exec("tskill IEDriverServer");
  17.         }catch(IOException ie){
  18.             System.out.println("failed to close IEDriverServer......");
  19.             ie.printStackTrace();
  20.         }
  21. }



这个就没法用上面submit按钮的方法了,于是我想,如果能将焦点设置到这个连接上,然后按【Enter】键,和点击的效果是一样的。于是我参考了资料[2],将代码修改为:

点击(此处)折叠或打开

  1. WebElement element = driver.findElement(By.xpath("//a[@class='return']"));
  2. Actions action = new Actions(driver);
  3. action.contextClick(element).perform();
  4. element.sendKeys(Keys.ESCAPE);
  5. element.sendKeys(Keys.ENTER);
测试通过!


 

这是用在连接上点击右键,然后按【ESC】键来设置焦点的,没有直接设置焦点的方法。有一点很奇怪,Actions的click()和doubleClick(),及单击和双击都不起作用,只有右键contextClick()起作用。另:Actions类在org.openqa.selenium.interactions下面。

 

还有记得在断言之前,间隔一两秒,不然会没操作完成,就去获取title了,然后断言失败。

 

 

5.       用处理连接的方法处理提交按钮

处理链接的方法,是否能用到submit按钮上呢?试试就知道了

点击(此处)折叠或打开

  1. WebElement element = driver.findElement(By.name("btnLogin"));
  2. Actions action = new Actions(driver);
  3. action.contextClick(element).perform();
  4. element.sendKeys(Keys.ESCAPE);
  5. element.sendKeys(Keys.ENTER);
成功!!!


 

 

参考资料

[1]   Selenium Webdriver submit() vs click() http://stackoverflow.com/questions/17530104/selenium-webdriver-submit-vs-click

[2]  webDriver中如何给元素设置焦点 http://www.ltesting.net/ceshi/open/kygncsgj/selenium/2013/0115/205906.html


转载自http://blog.chinaunix.net/uid-21340438-id-5158425.html
from dataclasses import dataclass import time from datetime import datetime from pathlib import Path from typing import List from selenium import webdriver from selenium.webdriver.common.by import By from selenium.webdriver.chrome.service import Service from selenium.webdriver.chrome.options import Options from selenium.webdriver.support.ui import WebDriverWait from selenium.webdriver.support import expected_conditions as EC from selenium.webdriver.remote.webelement import WebElement from contextlib import contextmanager import tkinter as tk @dataclass class EmailInfo: text: str element: WebElement @dataclass class DownloadConfig: folder_name: str patterns: List[str] @dataclass class LoginConfig: """登录配置""" base_url: str = "http://10.190.188.246/nsmail/index.html#login" username: str = "gwjxd_zhzx" password: str = "ZHzx@1108" class RevealDownloader: def __init__(self): self.today = datetime.now() self.month = str(self.today.month).lstrip('0') self.day = str(self.today.day).lstrip('0') self.base_path = Path('E:/GYK运行揭示1.5编辑') self.date_folder = f'{self.month}月{self.day}日揭示上午版' self.login_config = LoginConfig() self.setup_download_configs() self.driver = self.setup_chrome_driver() def setup_download_configs(self) -> None: """设置下载配置""" self.download_configs = { 'liuji': DownloadConfig( folder_name=f'4-柳机({self.month}月{self.day}日上午版)', patterns=[f"{self.month}月{self.day}日上午运行揭示正式版", f"{self.month}月{self.day}日上午运行揭示正式版(无新令)"] ), 'changguibao': DownloadConfig( folder_name=f'5-长轨包({self.month}月{self.day}日上午版)', patterns=[f"{self.month}月{self.day}日上午全线长轨达示包", f"{self.month}月{self.day}日上午工机段全线长轨达示包"] ) } def setup_chrome_driver(self) -> webdriver.Chrome: """配置Chrome浏览器""" options = Options() options.binary_location = r"D:\软件安装\特殊\Chrome 懒人绿色版\Chrome\chrome.exe" options.add_argument("--disable-extensions") options.add_argument("--no-sandbox") options.add_argument("--disable-gpu") options.add_argument('--lang=zh-CN') options.add_argument("--disable-blink-features=AutomationControlled") options.add_experimental_option("excludeSwitches", ["enable-automation"]) options.add_experimental_option('useAutomationExtension', False) prefs = { "profile.default_content_setting_values.automatic_downloads": 1, "download.prompt_for_download": False, "download.directory_upgrade": True, "safebrowsing.enabled": True } options.add_experimental_option("prefs", prefs) service = Service(r"D:\软件安装\特殊\Chrome 懒人绿色版\Chrome\chromedriver.exe") return webdriver.Chrome(service=service, options=options) def wait_for_element(self, by: By, value: str, timeout: int = 10) -> WebElement: """等待元素加载""" wait = WebDriverWait(self.driver, timeout) return wait.until(EC.presence_of_element_located((by, value))) def wait_for_clickable_element(self, by: By, value: str, timeout: int = 10) -> WebElement: """等待元素可点击""" wait = WebDriverWait(self.driver, timeout) return wait.until(EC.element_to_be_clickable((by, value))) def login(self) -> bool: """登录到邮箱系统""" try: print("\n开始登录邮箱系统...") # 访问登录页面 print(f"访问登录页面: {self.login_config.base_url}") self.driver.get(self.login_config.base_url) time.sleep(8) # 增加等待时间,让页面完全加载 print("页面加载完成,开始查找元素...") # 首先检查页面是否正确加载 print(f"当前页面标题: {self.driver.title}") print(f"当前页面URL: {self.driver.current_url}") # 搜索所有可能的输入框 print("\n搜索页面中的输入框...") all_inputs = self.driver.find_elements(By.TAG_NAME, "input") print(f"找到 {len(all_inputs)} 个输入框:") username_field = None password_field = None for i, input_elem in enumerate(all_inputs): try: input_id = input_elem.get_attribute("id") or "无ID" input_type = input_elem.get_attribute("type") or "无类型" input_placeholder = input_elem.get_attribute("placeholder") or "无placeholder" input_name = input_elem.get_attribute("name") or "无name" print(f" 输入框{i+1}: ID='{input_id}', type='{input_type}', placeholder='{input_placeholder}', name='{input_name}'") # 识别用户名输入框 if (input_id == "username" or "邮箱账号" in input_placeholder or "username" in input_name.lower() or "user" in input_id.lower()): username_field = input_elem print(f" -> 识别为用户名输入框") # 识别密码输入框 elif (input_id == "password" or input_type == "password" or "密码" in input_placeholder or "password" in input_name.lower()): password_field = input_elem print(f" -> 识别为密码输入框") except Exception as e: print(f" 检查输入框{i+1}时出错: {e}") # 输入用户名 if username_field: print(f"\n开始输入用户名: {self.login_config.username}") try: # 多种输入方式 self.driver.execute_script("arguments[0].focus();", username_field) username_field.clear() time.sleep(0.5) username_field.send_keys(self.login_config.username) time.sleep(0.5) # 验证输入结果 entered_value = username_field.get_attribute("value") print(f"用户名输入结果: '{entered_value}'") if entered_value != self.login_config.username: print("用户名输入不完整,尝试JS输入...") self.driver.execute_script(f"arguments[0].value = '{self.login_config.username}';", username_field) # 触发输入事件 self.driver.execute_script("arguments[0].dispatchEvent(new Event('input', { bubbles: true }));", username_field) except Exception as e: print(f"输入用户名时出错: {e}") else: print("❌ 未找到用户名输入框") return False # 输入密码 if password_field: print(f"\n开始输入密码...") try: self.driver.execute_script("arguments[0].focus();", password_field) password_field.clear() time.sleep(0.5) password_field.send_keys(self.login_config.password) time.sleep(0.5) # 验证密码是否输入(密码框通常不会显示实际值) entered_value = password_field.get_attribute("value") print(f"密码输入长度: {len(entered_value) if entered_value else 0}") if not entered_value or len(entered_value) == 0: print("密码输入失败,尝试JS输入...") self.driver.execute_script(f"arguments[0].value = '{self.login_config.password}';", password_field) self.driver.execute_script("arguments[0].dispatchEvent(new Event('input', { bubbles: true }));", password_field) except Exception as e: print(f"输入密码时出错: {e}") else: print("❌ 未找到密码输入框") return False # 查找登录按钮 print("\n搜索登录按钮...") login_button = None # 搜索所有可能的按钮元素 button_selectors = [ ("按钮标签", "//button"), ("输入按钮", "//input[@type='button' or @type='submit']"), ("包含登录的元素", "//*[contains(text(), '登录')]"), ("class包含btn的元素", "//*[contains(@class, 'btn')]"), ("class包含log的元素", "//*[contains(@class, 'log')]"), ("p标签", "//p") ] for desc, selector in button_selectors: try: elements = self.driver.find_elements(By.XPATH, selector) print(f" {desc}: 找到 {len(elements)} 个") for elem in elements: try: text = elem.text.strip() class_name = elem.get_attribute("class") or "" tag_name = elem.tag_name if text or "btn" in class_name.lower() or "log" in class_name.lower(): print(f" - {tag_name}: '{text}', class='{class_name}'") if ("登录" in text or "log" in class_name.lower()) and not login_button: login_button = elem print(f" -> 选择为登录按钮") except: pass except Exception as e: print(f" 搜索{desc}时出错: {e}") # 点击登录按钮 if login_button: print(f"\n点击登录按钮...") try: # 滚动到按钮位置 self.driver.execute_script("arguments[0].scrollIntoView(true);", login_button) time.sleep(1) # 尝试点击 self.driver.execute_script("arguments[0].click();", login_button) print("已点击登录按钮") time.sleep(8) except Exception as e: print(f"点击登录按钮时出错: {e}") return False else: print("❌ 未找到登录按钮") return False # 检查登录结果 print("\n检查登录结果...") current_url = self.driver.current_url print(f"登录后URL: {current_url}") if self.check_login_success(): print("✓ 登录成功!") return True else: print("❌ 登录失败") return False except Exception as e: print(f"登录过程出现异常: {str(e)}") import traceback traceback.print_exc() return False def check_login_success(self) -> bool: """检查登录是否成功""" try: # 增加等待时间 time.sleep(5) print("检查登录状态...") # 方法1: 检查URL是否发生变化 current_url = self.driver.current_url if "login" not in current_url.lower(): print("URL已改变,登录可能成功") return True # 方法2: 检查是否有错误提示 error_elements = self.driver.find_elements(By.XPATH, "//*[contains(text(), '错误') or contains(text(), '失败') or contains(text(), '用户名') or contains(text(), '密码')]") if error_elements: for error in error_elements: error_text = error.text.strip() if error_text and any(keyword in error_text for keyword in ['错误', '失败', '不正确', '无效']): print(f"发现错误信息: {error_text}") return False # 方法3: 检查是否不再有登录表单 login_forms = self.driver.find_elements(By.ID, "username") if not login_forms: print("登录表单已消失,登录成功") return True # 方法4: 检查是否有登录后的特征元素 # 邮件系统通常会有菜单、导航或者邮箱相关元素 success_indicators = [ "//span[contains(text(), '邮件')]", "//div[contains(@class, 'mail') or contains(@class, 'inbox')]", "//*[contains(text(), '收件箱') or contains(text(), '发件箱')]", "//a[contains(@href, 'mail') or contains(@href, 'inbox')]" ] for xpath in success_indicators: elements = self.driver.find_elements(By.XPATH, xpath) if elements: print(f"发现登录成功标志元素: {xpath}") return True # 方法5: 检查页面标题 page_title = self.driver.title if page_title and "登录" not in page_title and "login" not in page_title.lower(): print(f"页面标题已改变: {page_title}") return True print("未能确认登录状态") return False except Exception as e: print(f"检查登录状态时出错: {e}") return False def click_mail_menu(self) -> bool: """点击邮件菜单""" try: print("点击邮件菜单...") mail_span = self.wait_for_clickable_element( By.XPATH, "//span[contains(text(), '邮件')]" ) self.driver.execute_script("arguments[0].click();", mail_span) time.sleep(3) print("✓ 成功点击邮件菜单") return True except Exception as e: print(f"点击邮件菜单失败: {e}") return False def click_inbox(self) -> bool: """点击收件箱""" try: print("点击收件箱...") inbox_element = self.wait_for_clickable_element( By.XPATH, "//div[contains(@class, 'to_inbox') and contains(text(), '收邮件')]" ) self.driver.execute_script("arguments[0].click();", inbox_element) time.sleep(3) print("✓ 成功点击收件箱") return True except Exception as e: print(f"点击收件箱失败: {e}") return False def run_login_test(self) -> None: """运行登录测试""" try: print("开始登录测试...") print(f"目标网址: {self.login_config.base_url}") print(f"用户名: {self.login_config.username}") print(f"密码: {'*' * len(self.login_config.password)}") if self.login(): print("✓ 登录成功!") # 等待一下,让页面完全加载 time.sleep(3) # 打印当前页面信息用于调试 print(f"当前页面标题: {self.driver.title}") print(f"当前页面URL: {self.driver.current_url}") # 尝试寻找页面上的关键元素 print("\n搜索页面关键元素...") key_selectors = [ ("邮件相关", "//span[contains(text(), '邮件')]"), ("收件箱", "//*[contains(text(), '收件箱')]"), ("菜单项", "//div[@class]//span | //li//span | //a//span"), ("按钮", "//button | //input[@type='button'] | //div[@class*='btn']") ] for name, selector in key_selectors: try: elements = self.driver.find_elements(By.XPATH, selector) if elements: print(f" 找到{name}: {len(elements)}个") for i, elem in enumerate(elements[:3]): # 只显示前3个 try: text = elem.text.strip() if text: print(f" {i+1}. {text}") except: pass else: print(f" 未找到{name}") except Exception as e: print(f" 搜索{name}时出错: {e}") print("\n登录测试完成!") print("请查看浏览器窗口确认登录状态") print("按回车键继续...") input() else: print("✗ 登录失败") print("请检查:") print("1. 网址是否正确") print("2. 用户名和密码是否正确") print("3. 网络连接是否正常") except Exception as e: print(f"登录测试出错: {e}") import traceback traceback.print_exc() finally: print("5秒后关闭浏览器...") time.sleep(5) self.driver.quit() if __name__ == '__main__': try: RevealDownloader().run_login_test() except Exception as e: print(f"程序执行失败: {e}") time.sleep(3) 账号和密码输入没有问题,就是”登录”按钮点击不了,实现不了登录
最新发布
09-25
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值