Selenium的使用,以c#为例

在c#里使用Selenium ,
1 需要安装Selenium的包,分别为Selenium.support Selenium.webdriver Selenium.webdriver.msedgedriver(此处为msedge浏览器,如果是firefox 或者chrome,选择相应的就行)。
2 下载对应的msedgedriver.exe 这里注意的是,下载的版本要和nuget包的版本一致。比如Selenium.webdriver.msedgedriver 是106版本。下载的msedgedriver.exe也要是对应的版本。
3 不同的浏览器,要用不同的驱动

if (isUseExplore == "edge")
{
options = new EdgeOptions();
ConfigOptions(options, null);
driver = new OpenQA.Selenium.Edge.EdgeDriver(driverPath, (EdgeOptions)options, commandTimeout: TimeSpan.FromMinutes(20));
}
else
{
options = new ChromeOptions();
ConfigOptions(options, null);
driver = new OpenQA.Selenium.Chrome.ChromeDriver(driverPath, (ChromeOptions)options, commandTimeout: TimeSpan.FromMinutes(20));
}
driver.Manage().Timeouts().ImplicitWait = TimeSpan.FromSeconds(5);

下面我简单的罗列一下Actions类常用的方法:

Click : 点击元素。
ClickAndHold : 单击元素并保持按下的状态。
Release : 在元素上释放鼠标。
ContextClick : 单击鼠标右键。
DoubleClick : 双击元素。
MoveByOffset : 移动鼠标到特定位置或某个元素。
KeyDown : 按下键盘的某个按键。
KeyUp: 释放键盘的某个按键。
SendKeys : 向元素输入指定文本。
DragAndDrop : 拖拽元素。
DragAndDropToOffset : 拖拽元素到指定位置。
Build : 构建操作的链表。
Perform : 执行当前Built 的 Action。(即执行用户定义的一系列操作)

4 部分语法

//打开页面
driver.Navigate().GoToUrl(@"http://12.99.102.196:9080/corporbank/logon_pro.html");

//关闭浏览器
Driver.quit();

网银浏览器兼容性测试过程中,关闭浏览器后会有对话框,此问题解决方法如下:
public void logout()
{
System.Diagnostics.Process[] myProcesses;
       myProcesses = System.Diagnostics.Process.GetProcessesByName("chrome");
foreach (System.Diagnostics.Process instance in myProcesses)
{
instance.Kill();
}
}

// 执行js文件 需要将driver强制转换成JS执行器类型
((IJavaScriptExecutor) driver).ExecuteScript("js文件名");

//直接执行js代码

execute_script(同步执行)
execute_async_script(异步执行)
execute_script(script, *args): 执行js

return:可以返回js的返回结果

execute_script:arguments传参

driver.execute_script("return document.getElementById('kw').value")
driver.execute_script("return document.title;") # 返回网页标题
例如
js = 'arguments[0].setAttribute("style", arguments[1]);'
element = driver.find_element('id', 'kw')
style = 'background: red; border: 2px solid yellow;'
driver.execute_script(js, element, style)

page_height = driver.execute_script('return document.documentElement.scrollHeight;')

定位元素 优先使用id,name,classname,link;次之使用CssSelector();最后使用Xpath();
By.CssSelector(selector) ;类选择器
By.Id(id); id
By.LinkText(linkText); 根据文本
By.Name(name); 根据name
By.PartialLinkText(linkText); 根据链接内容
By.TagName(name); 根据tag 标签 例如 input
By.Xpath(xpathExpression); 根据xpath路径

driver.FindElements(OpenQA.Selenium.By.ClassName("videoBox")); 根据类名

Driver.FindElement(By.Id("amount")).SendKeys("500001"); 向文本框中输入值

driver.FindElement(By.Id("cp1_btnModify")).click(); 根据id,并点击

Driver.FindElement(By.Name(“quality”)).perform(); 根据元素的Name定位并操作

string order = "#resultTable.result_table tbody tr.bg1 td.center a";使用CssSelector定位并操作
driver.FindElement (By.CssSelector(order)).click();

//使用多个属性定位元素
Driver.FindElement(By.XPath("//input[@id='submit' and @value='下一步']")).click();

//使用绝对路径定位元素
string path = "/html/body/div[4]/div/div/div[2]/table/tbody/tr/td/a";
Driver.FindElement(By.Xpath(path)).click();

//清空文本框clear()
Driver.FindElement(By.Id("tranAmtText")).clear();

Selenium中清空文本框中的默认内容
//清空文本框clear()
Driver.FindElement(By.Id("tranAmtText")).clear();

Selenium中在指定的文本框中输入指定的字符串
//在文本框中输入指定的字符串sendkeys()
Driver.FindElement(By.Id("tranAmtText")).SendKeys(“123456”);

Selenium中移动光标到指定的元素上
//移动光标到指定的元素上perform
Actions action=new Actions(driver);
action.MoveToElement(Find(By.XPath("//input[@id='submit' and @value='确定']"))).Perform();

Selenium中点击按钮/链接
//点击按钮/链接click()
Driver.FindElement(By.XPath("//input[@id='submit' and @value='下一步']")).click();

Selenium中等待页面上的元素加载完成
//等待页面元素加载完成
//默认等待100秒
WebDriverWait wait = new WebDriverWait(driver, TimeSpan.FromSeconds(100));
//等待页面上ID属性值为submitButton的元素加载完成
wait.Until((d) => { return WaitForObject(By.Id("submitButton")); });
Selenium中模拟鼠标晃动
//模拟光标晃动movebyoffset()
Actions action = new Actions(driver);
action.MoveByOffset(2, 4);
Selenium中对iframe中元素的定位
切换焦点到id为固定值的iframe上

进入页面后,光标默认焦点在DefaultContent中,若想要定位到iframe 需要转换焦点
driver.SwitchTo().DefaultContent();
//切换焦点到mainFrame
driver.SwitchTo().Frame("mainFrame");
需要注意的是:切换焦点之后若想切换焦点到其他iframe上 需要先返回到defaultcontent,再切换焦点到指定的iframe上。

切换焦点到id值为动态值的iframe上
有时候 页面上浮出层的id为动态值,此时需要先获取所有符合记录的iframe放置在数组中,然后遍历数组切换焦点到目标iframe上。
如下方法:
protected string bizFrameId = string.Empty;
protected string bizId = string.Empty;
//获取动态iframe的id值
protected void SetIframeId()
{
ReadOnlyCollection els = driver.FindElements(By.TagName("iframe"));
foreach (var e in driver.FindElements(By.TagName("iframe")))
{
string s1 = e.GetAttribute("id");
if (s1.IndexOf("window") >= 0 && s1.IndexOf("content") >= 0)
{
bizFrameId = e.GetAttribute("id");
string[] ss = s1.Split(new char[] { '_' });
bizId = ss[1];
}
}
}

Selenium中关闭多个子Browser窗口

//获取所有的WindowHandle,关闭所有子窗口
string oldwin = driver.CurrentWindowHandle;
ReadOnlyCollection windows = driver.WindowHandles;
foreach (var win in windows)
{
if (win != oldwin)
{
driver.SwitchTo().Window(win).Close();
}
}
driver.SwitchTo().Window(oldwin);

Selenium中对下拉框的操作

//选择下拉框
protected void SelectUsage(string selectid, string text)
{
IWebElement select = Find(By.Id(selectid));
IList AllOptions = select.FindElements(By.TagName("option"));
foreach (IWebElement option in select.FindElements(By.TagName("option")))
{
if (option.GetAttribute("value").Equals(text))
option.Click();
}
}

Selenium中对confirm ,alert ,prompt的操作
//在本次浏览器兼容性测试项目中遇到的只有confirm和alert
//下面举例说明confirm和alert的代码,prompt类似
//confirm的操作
IAlert confirm = driver.SwitchTo().Alert();
confirm.Accept();
//Alert的操作
//个人网银中同样的业务有时候不会弹对alert,此时需要判断alert是否存在
//对Alert提示框作确定操作,默认等待50毫秒
protected void AlertAccept()
{
AlertAccept(0.05);
}

//等待几秒,可以为小数,单位为秒
protected void AlertAccept(double waitseSonds)
{
double nsleepMillon = waitseSonds * 1000;
int k=0;
int split=50;
IAlert alert = null;
do
{
k++;
Thread.Sleep(split);
alert = driver.SwitchTo().Alert();
}
while (k * split <= nsleepMillon || alert==null);
if (alert != null)
{
alert.Accept();
}
}

加载完成
try
{
new WebDriverWait(driver, TimeSpan.FromSeconds(1)).Until(
ExpectedConditions.ElementExists((By.ClassName("htl_room_table")))); //表示已加载完毕
}
finally
{

        }

Selenium WebDriver的截图功能
//WebDriver中自带截图功能
Screenshot screenShotFile = ((ITakesScreenshot)driver).GetScreenshot();
screenShotFile.SaveAsFile("test",ImageFormat.Jpeg);

Selenium内置了截图方法,只能截取浏览器中显示的内容,找到一个全屏截图的方式(内置截图+控制滚动条,图片拼接)
public static Bitmap GetEntereScreenshot(IWebDriver _driver)
{

        Bitmap stitchedImage = null;
        try
        {
            long totalwidth1 = (long)((IJavaScriptExecutor)_driver).ExecuteScript("return document.body.offsetWidth");//documentElement.scrollWidth");

            long totalHeight1 = (long)((IJavaScriptExecutor)_driver).ExecuteScript("return  document.body.parentNode.scrollHeight");

            int totalWidth = (int)totalwidth1;
            int totalHeight = (int)totalHeight1;

            // Get the Size of the Viewport
            long viewportWidth1 = (long)((IJavaScriptExecutor)_driver).ExecuteScript("return document.body.clientWidth");//documentElement.scrollWidth");
            long viewportHeight1 = (long)((IJavaScriptExecutor)_driver).ExecuteScript("return window.innerHeight");//documentElement.scrollWidth");

            int viewportWidth = (int)viewportWidth1;
            int viewportHeight = (int)viewportHeight1;


            // Split the Screen in multiple Rectangles
            List<Rectangle> rectangles = new List<Rectangle>();
            // Loop until the Total Height is reached
            for (int i = 0; i < totalHeight; i += viewportHeight)
            {
                int newHeight = viewportHeight;
                // Fix if the Height of the Element is too big
                if (i + viewportHeight > totalHeight)
                {
                    newHeight = totalHeight - i;
                }
                // Loop until the Total Width is reached
                for (int ii = 0; ii < totalWidth; ii += viewportWidth)
                {
                    int newWidth = viewportWidth;
                    // Fix if the Width of the Element is too big
                    if (ii + viewportWidth > totalWidth)
                    {
                        newWidth = totalWidth - ii;
                    }

                    // Create and add the Rectangle
                    Rectangle currRect = new Rectangle(ii, i, newWidth, newHeight);
                    rectangles.Add(currRect);
                }
            }

            // Build the Image
            stitchedImage = new Bitmap(totalWidth, totalHeight);
            // Get all Screenshots and stitch them together
            Rectangle previous = Rectangle.Empty;
            foreach (var rectangle in rectangles)
            {
                // Calculate the Scrolling (if needed)
                if (previous != Rectangle.Empty)
                {
                    int xDiff = rectangle.Right - previous.Right;
                    int yDiff = rectangle.Bottom - previous.Bottom;
                    // Scroll
                    //selenium.RunScript(String.Format("window.scrollBy({0}, {1})", xDiff, yDiff));
                    ((IJavaScriptExecutor)_driver).ExecuteScript(String.Format("window.scrollBy({0}, {1})", xDiff, yDiff));
                    System.Threading.Thread.Sleep(200);
                }

                // Take Screenshot
                var screenshot = ((ITakesScreenshot)_driver).GetScreenshot();

                // Build an Image out of the Screenshot
                Image screenshotImage;
                using (MemoryStream memStream = new MemoryStream(screenshot.AsByteArray))
                {
                    screenshotImage = Image.FromStream(memStream);
                }

                // Calculate the Source Rectangle
                Rectangle sourceRectangle = new Rectangle(viewportWidth - rectangle.Width, viewportHeight - rectangle.Height, rectangle.Width, rectangle.Height);

                // Copy the Image
                using (Graphics g = Graphics.FromImage(stitchedImage))
                {
                    g.DrawImage(screenshotImage, rectangle, sourceRectangle, GraphicsUnit.Pixel);
                }

                // Set the Previous Rectangle
                previous = rectangle;
            }
        }
        catch (Exception ex)
        {
            // handle
        }
        return stitchedImage;
    }

全屏截图
public static Image SnapshotV2(this IWebElement element, Bitmap bitmap)
{
Size size = new Size(
Math.Min(element.Size.Width, bitmap.Width),
Math.Min(element.Size.Height, bitmap.Height));
Rectangle crop = new Rectangle(element.Location, size);
return bitmap.Clone(crop, bitmap.PixelFormat);
}

常见问题:
1 等待:我们在处理对象的时候,对象并不能及时的“出现”,那么此时我们就需要进行等待了。
driver.Manage().Timeouts().SetPageLoadTimeout(TimeSpan.FromSeconds(20)); //这里的20,是以"s" 为单位,这里的数值可以根据实际情况来设置,
另一种
public IWebElement WaitForElement(IWebDriver driver, string el_id,int timeout) //找到元素就返回
{
IWebElement ele = null;
try
{
WebDriverWait wait = new WebDriverWait(driver, TimeSpan.FromSeconds(timeout));
ele = wait.Until((d) =>
{
return d.FindElement(By.Id(el_id));
});
}
catch
{
Console.WriteLine("12e");
}
return ele;
}

2获取窗体句柄:
driver.CurrentWindowHandle

3窗体转换:
driver.SwitchTo().Window();

4使用Actions
var xx = driver.FindElement(By.Id("id"));
Actions builder = new Actions(driver);
builder.MoveToElement(xx).Perform();

5根据链接文本定位对象(不太适用本地化测试)
driver.FindElement(By.PartialLinkText("登录"));

6处理弹出框
driver.SwitchTo().Alert().Accept()//简单讲就是点击yes
driver.SwitchTo().Alert().Dismiss()//点击No

7判断页面字符串
driver.PageSource.Contains("any word;");

8 窗体最大化
driver.Manage().Window.Maximize();

9 //等待搜索结果
WebDriverWait wait = new WebDriverWait(driver, TimeSpan.FromSeconds(10));
IWebElement searchResutl = null;
try
{
searchResutl = wait.Until((d) =>
{
return d.FindElement(By.ClassName("bdsug"));

                });
            }
            catch(Exception e)
            {
                Console.WriteLine("Timeout to find element:" + " "+ e.Message.ToString());
            }

10 //设置页面加载时间
driver.Manage().Timeouts().SetPageLoadTimeout(TimeSpan.FromSeconds(20));

11 //获取当前网页的句柄,使用与多个窗体
//那么我们需要的是第二个窗体
var currentWindowHandle = driver.WindowHandles[1];

            //因为要现在要处理的对象在新窗体上,所以这里要进行窗体转换
            driver.SwitchTo().Window(currentWindowHandle);

12 //移动鼠标
var xx = driver.FindElement(By.Id("cate_item_108698"));
Actions builder = new Actions(driver);
builder.MoveToElement(xx).Perform();

13 //Step 02 : 寻找需要操作的表格单元格。
var tableCol = driver.FindElement(By.XPath("//table[@id='tblTest']/tbody/tr/td[1]"));
var action = new Actions(driver);
action.KeyDown(Keys.Control);
action.Click(tableCol);
action.Build();
action.Perform();

   /// <summary>
    /// demo4 : 复杂交互
    /// </summary>
    [Fact(DisplayName = "Cnblogs.SeleniumAPI.Demo4")]
    public void SeleniumAPI_Demo4()
    {
        _output.WriteLine("Step 01 : 启动浏览器并打开博客园首页。");
        IWebDriver driver = new FirefoxDriver();
        driver.Url = "http://www.cnblogs.com";

        _output.WriteLine("Step 02 : 寻找需要操作的页面元素。");
        var divText = driver.FindElement(By.Id("site_nav_top"));
        var point = divText.Location;
        var width = int.Parse(divText.GetCssValue("width").Replace("px", string.Empty));

        _output.WriteLine("Step 03 : 选中文本信息。");
        var action = new Actions(driver);
        action
            .MoveByOffset(point.X, point.Y)         //移动鼠标到文本开头
            .ClickAndHold()                         //按下鼠标
            .MoveByOffset(point.X + width, point.Y) //移动鼠标到文本结束
            .Release()                              //释放鼠标
            .Build()
            .Perform();

        System.Threading.Thread.Sleep(5000);
        _output.WriteLine("Step 04 : 关闭浏览器。");
        driver.Close();
    }

参考
验证码和截图 https://www.cnblogs.com/zhaohadoopone/p/15338813.html
[小北De编程手记] : Selenium For C# 教程目录 https://www.cnblogs.com/vaevvaev/p/7041842.html
seleniumIDE替代品(Katalon插件安装和简单使用) https://blog.csdn.net/qq_36162514/article/details/80599214

posted @ 2022-10-09 20:56  过错  阅读(4444)  评论(0编辑  收藏  举报