我之前写的https://www.cnblogs.com/pu369/p/12365383.html文章,已实现用C#和Selenium 操控浏览器。下面总结一下常用操作(节选自https://www.jianshu.com/nb/10377047)
1、生成driver实例 可以用ChromeDriverService.CreateDefaultService()和ChromeOptions()进行配置
var driver = new OpenQA.Selenium.Chrome.ChromeDriver()
2、退出
driver.Quit():在完成操作后,同时关闭浏览器窗口和Weddriver会话
3、导航
//访问百度 driver.Navigate().GoToUrl("https://www.baidu.com");
4、元素定位(推荐用Xpath主要是可以从chrome DevTools中直接copy Xpath)
FindElement(By.Xpath("//div[@id="login"]/input"))
根据超链接的部分文字选取,比较方便
FindElement(By.PartialLinkText("Next"))
另外还有 By.Id() By.Name()By.LinkText()By.TagName()By. ClassName()By.CssSelector()
匹配多个元素
ReadOnlyCollection<IWebElement> elements = driver.FindElements(By.ClassName("mnav"));
5、通过CssSelector进行点击nth链接
driver.FindElement(By.CssSelector("p>a:nth-child(5)")).Click();
6、获取链接的数据属性
//获取链接地址 driver.FindElement(By.LinkText("Selenium")).GetAttribute("href"); //获取元素id driver.FindElement(By.LinkText("Selenium")).GetAttribute("id"); //获取元素文本 string text=driver.FindElement(By.LinkText("Selenium")).Text; //获取元素的TagName string tagName = driver.FindElement(By.LinkText("Selenium")).TagName;
7、切换窗口
//返回之前的窗口 driver.SwitchTo().Window(driver.WindowHandles[0]);
8、提交表单
driver.FindElement(By.Name("username")).SendKeys("UserName"); driver.FindElement(By.Name("pwd")).SendKeys("pwd"); driver.FindElement(By.XPath("//input[@value='注册-提交按钮']")).Click();
9、通过JavsScript点击按钮
IWebElement btn = driver.FindElement(By.Name("submit")); ((IJavaScriptExecutor)driver).ExecuteScript("arguments[0].click()", btn);
10、通过Name定位输入文本
driver.FindElement(By.Id("username")).Clear(); //先清空,防止和原有文本混在一起 driver.FindElement(By.Name("username")).SendKeys("username"); //多行文本直接加\r\n;用""可设置焦点
11、断言文本的值
IWebElement textValue = driver.FindElement(By.Id("userID")); textValue.SendKeys("testTextValue"); Console.WriteLine(textValue.GetAttribute("value")); Assert.AreEqual<string>("testTextValue", textValue.GetAttribute("value"));
12、改变只读或禁用状态文本框的值
((IJavaScriptExecutor)driver).ExecuteScript("document.getElementById('readOnlyId').value='改变只读文本的值'"); ((IJavaScriptExecutor)driver).ExecuteScript("document.getElementById('disableTextId').value='改变禁用文本的值'");
13、判断单选按钮状态
IWebElement femaleEle = driver.FindElement(By.Id("female")); bool flag = femaleEle.Selected;
14、选中第N个单选按钮
driver.FindElements(By.Name("gender"))[0].Click(); driver.FindElement(By.XPath("//input[1]")).Click();
请注意里面的下标,C#下标默认是从0开始,而XPath里面下标默认是从1开始。
15、复选框
IWebElement metroCheckbox = driver.FindElement(By.Id("metro")); if (!metroCheckbox.Selected) { metroCheckbox.Click(); }
连续调用FindElement方法选中复选框
driver.FindElement(By.Id("div2")).FindElement(By.Name("test")).Click();
16、通过文本选择列表-通过该方式仅能选中在浏览器中看到的选项。
IWebElement selectElem = driver.FindElement(By.Name("China")); SelectElement selectObj = new SelectElement(selectElem); selectObj.SelectByText("浦东新区");还可以SelectByValue SelectByIndex DeselectByText、DeselectByValue、DeselectByIndex DeselectAll 在使用SelectElement需要引用命名OpenQA.Selenium.Support.UI 。在标准的Selenium中,选择下拉列表的类是Select(比如Java),但在C#中Select是关键字,所以才换了一个名字。
17、通过循环选择列表
IWebElement selectElem = driver.FindElement(By.Name("China")); ReadOnlyCollection<IWebElement> options = driver.FindElements(By.TagName("option")); //循环每个列表选中一次 for (int i = 0; i < options.Count; i++) { options[i].Click(); } //循环选中一个列表 for (int i = 0; i < options.Count; i++) { if (options[i].Text.Contains("徐汇")) { options[i].Click(); } }
18、Selenium中Frame方法(主页中有1个mainFrame,其中又有两个平级的iframe)
driver.FindElement(By.Id("userName")).SendKeys("我在主页面中"); //第一次切换iFrame driver.SwitchTo().Frame("mainFrame"); Thread.Sleep(500); //第二次切换iFrame driver.SwitchTo().Frame("subFrame1"); driver.FindElement(By.Id("userNameId")).SendKeys("我在子iFrame-1"); driver.FindElement(By.Id("pwdId")).SendKeys("pwd"); //第三次切换iFrame,切换同级父iFrame,这时其实是位于mainFrame中 driver.SwitchTo().ParentFrame(); //第四次切换iFrame driver.SwitchTo().Frame("subFrame2"); driver.FindElement(By.Id("userNameId")).SendKeys("我在子iFrame-2"); driver.FindElement(By.Id("pwdId")).SendKeys("pwd"); //第六次切换iFrame-方法一,推荐方法一 driver.SwitchTo().ParentFrame(); //第六次切换iFrame-方法二 //driver.SwitchTo().DefaultContent(); //driver.SwitchTo().Frame("mainFrame"); driver.FindElement(By.Id("text1")).SendKeys("我已经切换到父iFrame啦"); //第六次切换iFrame driver.SwitchTo().DefaultContent(); driver.FindElement(By.Id("checkbox1")).Click(); driver.FindElement(By.Id("checkbox2")).Click();
注意方法SwitchTo().ParentFrame()和SwitchTo().DefaultContent()的区别
19、Selenium API 方法-主要的方法有Manage()、Navigate()、ITargetLocator()、Quit()等
//访问指定网址 driver.Navigate().GoToUrl("https://www.baidu.com"); //后退 driver.Navigate().Back(); //前进 driver.Navigate().Forward(); //刷新 driver.Navigate().Refresh();
控制浏览器外观
//移动浏览器 driver.Manage().Window.Position = new System.Drawing.Point(200,500); //用户自定义浏览器大小,需要使用到.NET里面的System.Drawing。 driver.Manage().Window.Size = new System.Drawing.Size(800,600); //浏览器最大化 driver.Manage().Window.Maximize(); //没有浏览器最小化方法,但我们可以通过移动窗口到指定位置实现同样的目的 driver.Manage().Window.Position = new System.Drawing.Point(-1500, 0);
拖动滚动条
driver.Url = "http://blog.csdn.net/"; driver.Manage().Window.Maximize(); Thread.Sleep(1000); IWebElement eles = driver.FindElement(By.PartialLinkText("公司简介")); int elesPostionX = eles.Location.X; int elesPostionY = eles.Location.Y; string js = "window.scroll(" + elesPostionX + "," + elesPostionY + ")"; ((IJavaScriptExecutor)driver).ExecuteScript(js); eles.Click();
在窗口和Tabs页面中切换
ReadOnlyCollection<string> windowsHandles = driver.WindowHandles; //切换到新窗口 driver.SwitchTo().Window(windowsHandles[1]); Assert.IsTrue(driver.PageSource.Contains("创立于1999年,是中国最大的开发者服务平台")); //返回最初的窗口 driver.SwitchTo().Window(windowsHandles[0]); ReadOnlyCollection<IWebElement> elements = driver.FindElements(By.XPath("//div[@id='pub_footerall']/dl/dd[1]/a")); Assert.AreEqual<int>(9,elements.Count); driver.Quit();
20、用户交互-需要引用OpenQA.Selenium.Interactions
20.1鼠标单击控件
IWebDriver driver=new ChromeDriver(); driver.Url = "https://www.baidu.com"; IWebElement eles = driver.FindElement(By.LinkText("关于百度")); Actions actionsObj = new Actions(driver); actionsObj.Click(eles).Perform();
上面是通过Actions类来实现鼠标单击,其实也可以直接使用IWebElement中自带的Click方法
20.2鼠标单击拖动-下面的代码演示的是从第1个控件单击并拖动至第5个控件,并选中这5个控件,如下所示:
driver.Url = "http://www.jqueryui.org.cn/demo/5640.html"; Thread.Sleep(1000); driver.Manage().Window.Maximize(); ReadOnlyCollection<IWebElement> items = driver.FindElements(By.XPath("//ol[@id='selectable']/li")); Assert.AreEqual<int>(7, items.Count); Actions actionsObj = new Actions(driver); actionsObj.ClickAndHold(items[0]).ClickAndHold(items[4]).Release().Perform();
最后一行代码连续调用了两次ClickAndHold()方法,==第1次调用代表是起始控件,第2次调用代表是结束控件,注意里面的下标是从0开始==
还可以是actionsObj.DoubleClick(eles).Perform();//双击
actionsObj.MoveToElement(eles).Perform();//移动
actionObj.DragAndDrop(soureEle, targetEle).Perform();//拖放
actionObj.ClickAndHold(soureEle).MoveToElement(targetEle).Release(targetEle).Perform();//按住、拖动、释放
20.3拖动进度条或滑块
driver.Url = "http://demo.lanrenzhijia.com/2015/drag1218/"; Thread.Sleep(1000); driver.Manage().Window.Maximize(); IWebElement origianlValueEle = driver.FindElement(By.Id("title")); Assert.AreEqual("0", origianlValueEle.Text); IWebElement sliderEle = driver.FindElement(By.Id("btn")); Actions actionsObj = new Actions(driver); actionsObj.DragAndDropToOffset(sliderEle, 100, 0).Perform(); Assert.AreEqual("51%", origianlValueEle.Text);
20.4单击鼠标右键菜单
driver.Url = "http://www.helloweba.com/demo/2017/basicContext/"; Thread.Sleep(1000); driver.Manage().Window.Maximize(); IWebElement btnEle = driver.FindElement(By.XPath("//button[contains(@class,'btn-success context')]")); Actions actionsObj = new Actions(driver); //点击右键菜单 actionsObj.ContextClick(btnEle).Perform(); IWebElement rightMenu = driver.FindElement(By.XPath("//div[@class='basicContext']/table/tbody/tr[2]")); rightMenu.Click(); IAlert alert = driver.SwitchTo().Alert(); string alertText = alert.Text; alert.Accept(); Assert.AreEqual<string>("Item clicked!",alertText);
20.5键盘操作
driver.Url = "https://www.baidu.com/"; Thread.Sleep(1000); driver.Manage().Window.Maximize(); IWebElement searchBoxEle = driver.FindElement(By.Id("kw")); searchBoxEle.SendKeys("在百度搜索框中输入一段文字"); Thread.Sleep(1000); Actions actionObj = new Actions(driver); //使用Ctrl+A全选输入的文字 actionObj.Click(searchBoxEle).KeyDown(Keys.Control).SendKeys("a").KeyUp(Keys.Control).Perform(); //使用键盘Backspace删除刚才输入的文字 actionObj.SendKeys(Keys.Backspace).Perform();
注意上面代码最后一行使用了Actions类中的SendKeys()方法,该方法与IWebElement接口中的SendKeys()方法不一样,注意区别
21、设置等待时间
21.1显示等待-它指的是让Webdriver等待某个条件成立时继续执行,否则则是在达到设定的时间后,抛出超时异常。(代码涉及到了C#中的委托和lambda表达式)
WebDriverWait explicitWait = new WebDriverWait(driver, TimeSpan.FromSeconds(10)); string text = explicitWait.Until(d => d.FindElement(By.Id("status"))).Text; Assert.IsTrue(text.Contains("invalid username or password"));
21.2隐式等待-允许Web页面中的元素在特定的时间内加载完成。如果超出了设定的时间,指定的元素仍没有被加载完,则抛出异常。**默认的时间为 0 **
driver.Manage().Timeouts().ImplicitWait(TimeSpan.FromSeconds(10)); string text = driver.FindElement(By.Id("status")).Text; Assert.IsTrue(text.Contains("invalid username or password"));
22、弹出窗口
22.1文件上传弹出窗口操作
string filePath = @"C:\类和对象.jpg"; driver.FindElement(By.Id("fileUpload")).SendKeys(filePath);
22.2JavaScript弹出窗口
方法一:使用Selenium API中的IAlert接口
driver.FindElement(By.XPath("//input[@value='显示确认对话框']")).Click(); IAlert alert = driver.SwitchTo().Alert(); if (alert.Text.Contains("请点击")) { alert.Accept(); } else { alert.Dismiss(); }
方法二:使用JavaScript
((IJavaScriptExecutor)driver).ExecuteScript("window.confirm=function(){return true;}"); ((IJavaScriptExecutor)driver).ExecuteScript("window.alert=function(){return true;}"); ((IJavaScriptExecutor)driver).ExecuteScript("window.prompt=function(){return true;}"); driver.FindElement(By.XPath("//input[@value='显示确认对话框']")).Click();
非原生模态对话框,就比较容易了
driver.FindElement(By.XPath("//button[contains(@class,'btn btn-default')]")).Click();
在测试过程中,弹出窗口未及时处理,将导致测试失败。对于这种情况,我们通过给测试方法
添加属性TimeoutAttribute来指定最长的时间。
即在C#方法前加上[TestMethod]和
[Timeout(10*1000)] //超时时间为10秒
23、Assert-微软框架中提供的断言有很多个,我们常用的有Assert.IsTrue()、Assert.IsFalse()、Assert.AreEqual()、Assert.AreNotEqual()等包含常规类型和泛型
Assert.IsTrue(driver.PageSource.Contains(expectText));
24、JavaScript中的OnXXXX事件
24.1当我们使用代码正常输入文字后,相应的文字并没有显示出来。这个时候其实是没有触发OnClick()方法,我们可以再次单击一下即可,示例代码如下:
driver.FindElement(By.Id("testText")).Click(); driver.FindElement(By.Id("testText")).SendKeys("Test JavaScript OnClick()方法"); Assert.AreEqual<string>("最多允许32个字符", driver.FindElement(By.Id("tip")).Text);
24.2触发OnChange()事件(代码使用到JQuery的一些方法,在页面加载时需要添加jquery.js文件)
driver.FindElement(By.Id("onchange")).SendKeys("Test JavaScript OnChange()方法"); string js = @"$('#onchange').trigger('change')"; ((IJavaScriptExecutor)driver).ExecuteScript(js); Assert.AreEqual<string>("测试OnChange方法", driver.FindElement(By.Id("change")).Text);
24.3使用JavaScript调整滚动条
driver.Url = "http:www.jb51.net"; driver.Manage().Window.Maximize(); //调整到底部 string jsToBottom = "window.scrollTo(0,document.body.scrollHeight)"; ((IJavaScriptExecutor)driver).ExecuteScript(jsToBottom); //调整到指定位置 IWebElement ele = driver.FindElement(By.XPath("//div[@id='mainbody']/div[8]/div[4]/h2/span[1]")); int elePosition = ele.Location.Y; string jsToCustomerPostion = "window.scrollTo(0,"+elePosition+")"; ((IJavaScriptExecutor)driver).ExecuteScript(jsToCustomerPostion);
24.4使用键盘组合键调整滚动条
driver.Url = "http:www.jb51.net"; driver.Manage().Window.Maximize(); //使用键盘Ctrl+End到底部 driver.FindElement(By.TagName("body")).SendKeys(Keys.Control + Keys.End); //使用键盘Ctrl+Home回到顶端 driver.FindElement(By.TagName("body")).SendKeys(Keys.Control+Keys.Home);
25、基于JQuery的插件:Chonsen
Thread.Sleep(2000); driver.FindElement(By.XPath("//div[@id='dept1_chosen']/a[contains(@class,'chosen-single')]")).Click(); ReadOnlyCollection<IWebElement> eles = driver.FindElements(By.XPath("//div[@id='dept1_chosen']//div[contains(@class,'chosen-drop')]//ul/li[contains(@class,'active-result')]")); for (int i = 0; i < eles.Count; i++) { if (eles[i].Text == "财务") { eles[i].Click(); break; } }