隐藏

Selenium的使用,以c#为例

发布:2024/1/23 14:50:57作者:管理员 来源:本站 浏览次数:285



在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