c#和python通用,使用Selenium自动化测试库单点登录、自动修改密码等各种自动化操作
接上个帖子,之前使用的是油猴脚本tampermonkey+js代码,通过在浏览器安装插件执行js脚本的方式自动填充账号密码登录框,实现另类的单点登录。后续实施起来比较麻烦,需要帮用户安装脚本文件,并且脚本更新比较麻烦,需要手动一个个替换js代码,另外油猴脚本插件存在浏览器不兼容或者被删除的可能。
于是便找到了Selenium这个库,通过学习和编写测试代码也比较完善的实现了这个功能,记录和分享一下代码和解决方案。
Selenium在Python和c#中均可直接引入并使用,由于我的业务是做来后台单点登录和一键修改密码的操作,所以通过后台API调用的方式来实现是最完美的,而.net程序
的打包和更新更方便,所以便从python更改成了c#程序
话不多说,上代码和实现步骤:
[*]使用vs或者Rider创建一个.net core解决方案(不需要写web api项目的话创建一个简单的桌面解决方案也行)
[*]引入Selenium库,大概就这些:
using OpenQA.Selenium.Interactions;
using SSO.WEBAPI.Controllers;
namespace SSO.WEBAPI.Services;
using OpenQA.Selenium;
using OpenQA.Selenium.Chrome;
using OpenQA.Selenium.Support.UI;
using SeleniumExtras.WaitHelpers;
3.使用这个库执行自动化测试。Selenium的大概功能就是可以控制打开浏览器服务窗口,然后这个浏览器窗口是完全由Selenium控制的,你可以通过代码来控制浏览器打开指定的web页面,然后获取页面上的所有元素,通过调试将需要的元素赋值、点击按钮、点击链接、前往新的页面、在新的页面继续控制各个元素的事件和值,很多网站很少会更新改这个代码,所以大概写好一次就能一直用了。我这边以登录修改密码为例:
try
{
// 配置ChromeDriver服务
_service = ChromeDriverService.CreateDefaultService();
// _service.HideCommandPromptWindow = true; // 隐藏命令行窗口
// 启动Chrome浏览器
_options = new ChromeOptions();
_options.AddArgument("--start-maximized");
_options.AddArgument("--headless"); // 无头模式
// 启动ChromeDriver时传入service和options
IWebDriver driver = new ChromeDriver(_service, _options, TimeSpan.FromSeconds(5));
// 导航到GitLab登录页面
driver.Navigate().GoToUrl(pwdRequest.Url);
// 等待页面加载(可以使用显式等待,简化为线程休眠)
Thread.Sleep(100);
// 查找并填充用户名字段
var usernameField = driver.FindElement(By.Id("user_login"));
usernameField.SendKeys(pwdRequest.Username); // 替换为你的GitLab用户名
// 查找并填充密码字段
var passwordField = driver.FindElement(By.Id("user_password"));
passwordField.SendKeys(pwdRequest.Password); // 替换为你的GitLab密码
// 查找并点击登录按钮
var loginButton = driver.FindElement(By.CssSelector("button"));
loginButton.Click();
// 等待登录过程完成(可以根据页面变化调整等待时间)
// System.Threading.Thread.Sleep(1000);
// 检查是否登录成功(可选,验证是否跳转到登录后的页面)
var wait = new WebDriverWait(driver, TimeSpan.FromSeconds(2));
// 等待特定ID的元素出现
var sidebarHeading = wait.Until(ExpectedConditions.ElementIsVisible(By.Id("super-sidebar-heading")));
//特定元素出现,前往新页面
if (sidebarHeading.Displayed)
{
driver.Navigate().GoToUrl(pwdRequest.PwdUrl);
Thread.Sleep(100);
//找到元素并填充
var oldPwd = driver.FindElement(By.Id("user_password"));
oldPwd.SendKeys(pwdRequest.Password);
var newPwd = driver.FindElement(By.Id("user_new_password"));
newPwd.SendKeys(pwdRequest.NewPassword);
var passPwd = driver.FindElement(By.Id("user_password_confirmation"));
passPwd.SendKeys(pwdRequest.NewPassword);
var saveButton = driver.FindElement(By.CssSelector("button"));
saveButton.Click();
return true;
}
return false;
}
catch (Exception e)
{
// Log.Error("An error occurred: " + e.Message);
return false;
}
代码看不清可以看图片附件,每一步都有注释分析的,查找页面的元素直接浏览器f12打开控制台找即可,演示图也在最后
另外调试获取页面元素的方式很多很多,通过id,class,name,甚至文本内容,这个如果有学前段的朋友应该挺了解的。
注意如果页面中有iframe标签的话,需要切换到iframe标签内才能获取iframe标签内的元素,我被这个坑了好久:
// 切换到 iframe
var iframeElement = driver.FindElement(By.ClassName("lui_widget_iframe"));
driver.SwitchTo().Frame(iframeElement); 如果需要调用源码的话我后续再整理分享一下 谢谢分享!收藏先 自动化测试学习中,谢谢分享 学习中,希望自己越来越强大💪('ω'💪)! 求PYthon源码案例 tzq001 发表于 2024-9-6 10:00
求PYthon源码案例
这是python的示例,用的djiango写的web案例
from django.http import JsonResponse
from django.views.decorators.csrf import csrf_exempt
import json
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.common.exceptions import NoSuchElementException, TimeoutException
from webdriver_manager.chrome import ChromeDriverManager
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
# 初始化 WebDriver
def initialize_login_driver():
chrome_options = Options()
chrome_options.add_argument("--start-maximized")
chrome_options.add_argument("--disable-extensions")
chrome_options.add_argument("--disable-popup-blocking")
chrome_options.add_argument("--disable-infobars")
chrome_options.add_argument("--disable-notifications")
chrome_options.add_experimental_option("useAutomationExtension", False)
chrome_options.add_experimental_option("detach", True)# 保持浏览器打开
# chrome_options.add_argument("--headless")# Uncomment if you want headless mode
driver = webdriver.Chrome(service=Service(ChromeDriverManager().install()), options=chrome_options)
return driver
def initialize_password_driver():
chrome_options = Options()
chrome_options.add_argument("--start-maximized")
chrome_options.add_argument("--disable-extensions")
chrome_options.add_argument("--disable-popup-blocking")
chrome_options.add_argument("--disable-infobars")
chrome_options.add_argument("--disable-notifications")
chrome_options.add_experimental_option("useAutomationExtension", False)
chrome_options.add_experimental_option("detach", True)# 保持浏览器打开
# chrome_options.add_argument("--headless")# Uncomment if you want headless mode
driver = webdriver.Chrome(service=Service(ChromeDriverManager().install()), options=chrome_options)
return driver
def login_to_gitlab(driver, url, username, password):
try:
driver.get(url)
wait = WebDriverWait(driver, 10)
username_input = wait.until(EC.presence_of_element_located((By.ID, 'user_login')))
password_input = wait.until(EC.presence_of_element_located((By.ID, 'user_password')))
username_input.clear()
username_input.send_keys(username)
password_input.clear()
password_input.send_keys(password)
login_button = wait.until(EC.element_to_be_clickable((By.XPATH, '//button[@type="submit"]')))
login_button.click()
wait.until(EC.presence_of_element_located((By.CLASS_NAME, 'mobile-overlay')))
return {"message": "Login successful"}
except TimeoutException:
return {"error": "Timeout waiting for elements"}
except NoSuchElementException:
return {"error": "Element not found"}
except Exception as e:
return {"error": str(e)}
finally:
return {"message": "Login successful"}
# driver.quit()
@csrf_exempt
def login_view(request):
if request.method == 'POST':
try:
data = json.loads(request.body)
login_type = data.get('type')
url = data.get('url')
username = data.get('username')
password = data.get('password')
if not url or not username or not password:
return JsonResponse({"error": "Missing URL, username, or password"}, status=400)
driver = initialize_login_driver()
if login_type == "gitlab":
result = login_to_gitlab(driver, url, username, password)
return JsonResponse(result)
except json.JSONDecodeError:
return JsonResponse({"error": "Invalid JSON"}, status=400)
else:
return JsonResponse({"error": "Only POST method allowed"}, status=400)
@csrf_exempt
def reset_password(request):
if request.method == 'POST':
try:
data = json.loads(request.body)
reset_type = data.get('type')
login_url = data.get('url')
update_password_url = data.get("password_url")
username = data.get('username')
password = data.get('password')
new_password = data.get("new_password")
if not login_url or not username or not password:
return JsonResponse({"error": "Missing URL, username, or password"}, status=400)
driver = initialize_password_driver()
if reset_type == "gitlab":
result = reset_to_gitlab(driver, login_url, username, password,update_password_url,new_password)
return JsonResponse(result)
except json.JSONDecodeError:
return JsonResponse({"error": "Invalid JSON"}, status=400)
else:
return JsonResponse({"error": "Only POST method allowed"}, status=400)
def reset_to_gitlab(driver, url, username, password, update_url, new_pwd):
try:
print("Navigating to login page...")
driver.get(url)
wait = WebDriverWait(driver, 10)
# 登录操作
print("Looking for username input field...")
username_input = wait.until(EC.presence_of_element_located((By.ID, 'user_login')))
print("Found username input field.")
print("Looking for password input field...")
password_input = wait.until(EC.presence_of_element_located((By.ID, 'user_password')))
print("Found password input field.")
username_input.clear()
username_input.send_keys(username)
password_input.clear()
password_input.send_keys(password)
print("Looking for login button...")
login_button = wait.until(EC.element_to_be_clickable((By.XPATH, '//button[@type="submit"]')))
print("Found login button, clicking...")
login_button.click()
print("Waiting for page to load after login...")
wait.until(EC.presence_of_element_located((By.CLASS_NAME, 'mobile-overlay')))
print("Login successful, navigating to update password page...")
# 跳转到修改密码页面
driver.get(update_url)
print(f"Navigated to {update_url}, waiting for password fields...")
# 等待密码修改页面元素加载
wait.until(EC.presence_of_element_located((By.ID, 'user_password')))
print("Found old password field.")
# 修改密码
old_pwd_input = driver.find_element(By.ID, 'user_password')
print("Found old password input field.")
new_password_input = driver.find_element(By.ID, 'user_new_password')
print("Found new password input field.")
user_password_confirmation = driver.find_element(By.ID, 'user_password_confirmation')
print("Found password confirmation input field.")
old_pwd_input.clear()
old_pwd_input.send_keys(password)
new_password_input.clear()
new_password_input.send_keys(new_pwd)
user_password_confirmation.clear()
user_password_confirmation.send_keys(new_pwd)
print("Password updated successfully.")
return {"message": "Password updated successfully"}
except TimeoutException:
print("Timeout waiting for elements")
return {"error": "Timeout waiting for elements"}
except NoSuchElementException:
print("Element not found")
return {"error": "Element not found"}
except Exception as e:
print(f"An error occurred: {str(e)}")
return {"error": str(e)}
# finally:
# driver.get(update_url)
# driver.quit() 52pjdana 发表于 2024-9-6 11:19
这是python的示例,用的djiango写的web案例
from django.http import JsonRes ...
十分感谢分享
页:
[1]