Selenium 系列:第二章,通过类型深入了解 Selenium 的精华
本文旨在演示 ByType 选择器在 Selenium 中的不同用法。这是 API 的核心,通过类型查找元素。理解这些 ByType 对于导航、选择和使用 Web 元素进行测试至关重要。让我们开始自动化测试吧!
引言
本文将带领我们从零基础到精通,学习 Selenium 中所有不同的 By 类型和 Find Element(s) API 方法,并使用 MsTest 和 Shouldly。这是 API 的核心,如果我没记错的话,FindElement 和 FindElements 应该是使用 Selenium 时最常用的 API 方法调用…所以,让我们开始吧!
背景
如果您需要回顾 Selenium 系列第一章,可以在下方找到,并查看所需的依赖项,源代码已附带,或可在下方列出的我的 GitHub 帐户中找到。
https://codeproject.org.cn/Articles/1166904/Selenium-Series-Chapter-Getting-Started https://github.com/seanrand57/SeleniumSeries我们将使用 Selenium,深入了解 Find Element 和 Find Elements API 方法,访问菜单项、文本框、按钮、文本,基本上是浏览器中的任何内容,我们都将能够访问。这听起来很酷,事实也确实如此,因为在我多年的 Selenium 开发和使用经验中,我发现它是你所做事情的核心,以及如何通过 DOM (Document Object Model) 访问浏览器元素。
什么是 By 类型?
By 类型,这是告诉 Selenium 如何在页面上查找元素的方式。听起来很酷,而且确实如此,因为有很多方法可以做到这一点,但首先,让我们稍微回顾一下 DOM,然后再深入探讨,因为我们是慢节奏开始,在接下来的章节中会加快速度。
首先,由于我们目前在测试中使用 Firefox 作为浏览器,请在您的机器上打开 Firefox 浏览器,然后导航到我们要测试的页面。
http://www.seleniumhq.org/右键单击浏览器,如下图所示,然后选择菜单项,我们看到了什么?运气好的话,它应该和我的图片一样。
- 现在我们可以看到 Selenium HQ 首页,底部是浏览器检查面板,显示了 DOM。理解 DOM 和知道如何抓取元素对于 UI Web 自动化测试至关重要,我怎么强调都不为过,然而它非常容易上手,希望能在这个章节结束时让你掌握,如果我做得好的话!
- 浏览器的检查面板包含了浏览器用来构建网页供我们查看的源代码或 DOM。这意味着什么?
- 请注意,在检查面板中,我点击的地方显示:<a href="/" title="Return to Selenium home page">Browser Automation</a>。在网页中,它对应于“Browser Automation”链接,通过“/”的 href,我们可以返回到主页。现在我们看到了如何右键单击网页上我们要测试的某个元素并检查该元素以在 Selenium 中使用,我们现在需要使用 API 来与之交互!这就是乐趣开始的地方,缓慢的部分已经过去了!
Selenium API 允许我们使用 FindElement 或 FindElements 方法来捕获文本框、图标、文本、按钮,通过类型进行查找,所以让我们看看下面的代码片段,它们是什么。
下面展示了使用 FindElement 抓取 WebElements 的所有方法,它为我们提供了一个特定的项,例如搜索按钮。或者使用 FindElements 方法查找元素列表,例如可以获得屏幕上的所有按钮。另外,下面有一个非常酷的东西,我们看到 element1 中明确使用了 By.Id(""),但看看 element9…太棒了,我们可以直接写 FindElementById("")。我可能是因为之前在 Selenium 中写过代码,所以这可以减轻测试人员的思考负担,让他们只专注于方法签名所需的字符串值。
// Finding one Specific Element using a Specifc By type var element1 = driver.FindElement(By.Id("")); var element2= driver.FindElement(By.LinkText("")); var element3 = driver.FindElement(By.PartialLinkText("")); var element4 = driver.FindElement(By.ClassName("")); var element5 = driver.FindElement(By.CssSelector("")); var element6 = driver.FindElement(By.Name("")); var element7 = driver.FindElement(By.TagName("")); var element8 = driver.FindElement(By.XPath("")); // Finding one Specific Element using new Selenium Methods // Pretty cool we only have to supply a string value to given method // signature var element9 = driver.FindElementById(""); var element10 = driver.FindElementByLinkText(""); var element11 = driver.FindElementByPartialLinkText(""); var element12 = driver.FindElementByClassName(""); var element13 = driver.FindElementByCssSelector(""); var element14 = driver.FindElementByName(""); var element15 = driver.FindElementByTagName(""); var element16 = driver.FindElementByXPath(""); // Finding a List of WebElements using a Specific By Type var elements18 = driver.FindElements(By.LinkText("")); var elements19 = driver.FindElements(By.PartialLinkText("")); var elements20 = driver.FindElements(By.ClassName("")); var elements21 = driver.FindElements(By.CssSelector("")); var elements22 = driver.FindElements(By.Name("")); var elements23 = driver.FindElements(By.TagName("")); var elements24 = driver.FindElements(By.XPath("")); // Finding a List of WebElements using a Specific By Type var elements25 = driver.FindElementsById(""); var elements26 = driver.FindElementsByLinkText(""); var elements27 = driver.FindElementsByPartialLinkText(""); var elements28 = driver.FindElementsByClassName(""); var elements29 = driver.FindElementsByCssSelector(""); var elements30 = driver.FindElementsByName(""); var elements31 = driver.FindElementsByTagName(""); var elements32 = driver.FindElementsByXPath("");
开始测试!!!
请记住,在第一章中我们讨论了“特征”,而我们在第二章,将使用包含本文所有测试的第二章特征,如下所示。希望,如果你右键单击“Chapter-2”并运行所有这些测试,它们会变成绿色并通过,如下图所示。
要在测试资源管理器中按特征排序,我们右键单击测试面板(如下图所示)-> 分组方式 -> 特征。
我们将首先查看并逐行运行的测试名为:ById_FindingTheSearchTextBox_And_Searching
让我们深入其中,做我们来这里该做的事,测试、学习并提升我们的 Selenium 知识!
测试的**Arrange**部分是我们第一章用来初始化 Web 浏览器并导航到 SeleniumHQ 网站的部分。这一部分我们可以跳过,但想提及它与第一章没有区别。
现在,**Act**部分是我们来这里的目的!请注意测试名称为 ById,其余测试的名称如下图所示。现在我们捕获了两个元素:**searchBox 和 SearchButton**。用户现在想要在那个 Web 元素 Search Box 中输入文本,我们通过使用 **SendKeys** 来完成。现在我们在 Searchbox 中填入了文本,我们想要**点击搜索按钮**。这非常简单,因为我们有名为 searchButton 的 Web 元素,所以我们只需调用 searchButton.Click()。多么简单、易读、出色啊?我们填入了搜索框,然后执行了搜索。我们想要**断言**我们是否在 Selenium 网站使用的 Google 自定义搜索页面上,以确保搜索已发生。当然,我们可以进一步细化这个断言,但我们的测试是为了强调我们如何找到元素并使用它们。
实际上,查找元素就是这么简单,只需使用 FindElement 或按类型查找 FindElement,如果它可用,我们就可以像用户一样使用它。真正强大且简单。
public void ById_FindingTheSearchTextBox_And_Searching()
{
// Arrange
var driver = new FirefoxDriver();
driver.Manage().Window.Maximize();
driver.Manage().Timeouts().ImplicitlyWait(TimeSpan.FromSeconds(10));
driver.Navigate().GoToUrl("http://www.seleniumhq.org/");
//Act - Clicking the Search Box, entering text and searching
var searchBox = driver.FindElement(By.Id("q"));
var searchButton = driver.FindElement(By.Id("submit"));
// Send Text to the Search box and press the Search Button "Go"
// more to come on Sending Keys and Click / Actions in a later Chapter ;-)
searchBox.SendKeys("Selenium Find Elements");
searchButton.Click();
var wait = new WebDriverWait(driver, TimeSpan.FromSeconds(5));
wait.Until(drv => drv.Url.Contains("google.com"));
//Assert
driver.Title.ShouldNotBeEmpty();
driver.Title.ShouldBe("Google Custom Search");
// clean up
driver.Quit();
}
第二章中的测试
下面是第二章中的测试列表,可以在解决方案的类文件中找到。
Tests -> 005_Using_By_Types -> UsingByTypes.cs
本章的以下测试部分向我们展示了我们可以执行相同的测试,但使用不同的 By 类型来实现相同的结果。
这有什么用?并非浏览器 DOM 中的每个元素都有 Id,因此我们需要通过 XPath、CSS 或 LinkText 来获取它们。这是关键,Selenium 允许我们在 Web 实现方面保持灵活性和敏捷性。
- ByIds_FindingTheMenuItems_And_NavigatingTheSite
- ByLinkText_FindingTheAboutMenuItem_And_NavigatingToThePage
- ByTag_FindingTheAboutMenuItem_And_NavigatingToThePage
- ByCss_FindingTheAboutMenuItem_And_NavigatingToThePage
- ByXPath_FindingTheAboutMenuItem_And_NavigatingToThePage
var aboutMenuItem = driver.FindElement(By.LinkText("About")); var menuItem = driver.FindElement(By.CssSelector("li#menu_about"));
这个测试展示了 FindElementById() API 方法的执行,从源代码看非常酷,请看下面的代码片段。
- FindingTheMenuItems_By_New_ExtensionMethnds
该测试还向我们展示了,如果我们找到一个元素并想点击它,我们可以在一行干净的代码中完成,很酷!但请记住,这已经涉及到了即将推出的**Selenium Actions**文章 :-)
//Act - This code snippet shows us how to find the menu items and click each of them in turn. // 4 lines of code = 4 find and actions taken place. Really nice and clean. driver.FindElementById("menu_projects").Click(); driver.FindElementById("menu_download").Click(); driver.FindElementById("menu_documentation").Click(); driver.FindElementById("menu_support").Click(); driver.FindElementById("menu_about").Click();
- FindingTheMenuItems_And_NavigatingUsingClickExtensions
- FindingThe_SeleniumIcon_ByClassName
- FindingThe_SearchBox_ByName_And_Searching
下面的两个测试向我们展示了我们如何找到一个元素,或者找到很多元素然后从列表中找到特定的一个。当我们在网页中有表格时,我们可能会使用 FindElements 选项,因为有时很难找到一个特定的表格列,然后捕获所有表格,迭代元素查找单元格中的文本并进行断言。
- UsingFindElement
- UsingFindElements - 下面展示了我们使用**FindElementsByTagName**“a”,它代表了网站上的所有超链接。然后我们专门查找“About us”链接并点击它。这只是展示了如何使用 Web 元素列表,在你的测试生涯中肯定会需要这些。
public void UsingFindElements() { // Arrange var driver = new FirefoxDriver(); driver.Manage().Window.Maximize(); driver.Manage().Timeouts().ImplicitlyWait(TimeSpan.FromSeconds(10)); driver.Navigate().GoToUrl("http://www.seleniumhq.org/"); //Act - finding all anchor tags denoted by "a" which are links on the site. var allLinks = driver.FindElementsByTagName("a"); // Find the link text which is About and click it foreach (var link in allLinks) if (link.Text.Equals("About")) { link.Click(); break; } //Assert var wait = new WebDriverWait(driver, TimeSpan.FromSeconds(5)); wait.Until(drv => drv.Title.Contains("About")); driver.Url.ShouldBe("http://www.seleniumhq.org/about/"); // clean up driver.Quit(); }
快速提示
FindElement() API 方法会搜索整个网页,找到第一个符合我们 ByType 条件的元素并抓取它。例如,如果我们网站上有两个名为“**Click Me**”的链接。然而,我们可能想抓取第二个“Click Me”链接,因为它在点击时会将我们导航到另一个网页。如果我们使用 FindByLinkText("Click Me") 方法,Selenium 会找到第一个链接,认为它找到了,并将它返回给你,而你想要的却是第二个 Click Me 链接。
当你遇到类似元素且测试出现意外失败时,请记住这一点,因为这可能会让你陷入困境。我分享出来,希望在你遇到这种情况时能为你节省一些时间,大多数人都会遇到!
希望你执行所有测试,并深入研究第二章的解决方案,使用这些新的 By 类型!
我们在本章(希望)学到了什么?
如果你读到这里,首先感谢你,我希望我们学到了:
- 所有 By 类型及其用法。
- 如何将 By 类型与 Find Element 和 Find Elements 一起使用。
- 如何使用新的 FindElementByType 方法,这是我在 Selenium 3.0+ 中最喜欢的新增功能。
- 何时使用 FindElement 与 FindElements。
- 一个快速提示:在找到一个元素时要小心,当存在多个相同元素且你不想获取第一个时。
- 所有测试都应该在 Visual Studio 2015, .NET C# 中本地运行、执行并通过。
- 希望你现在已经掌握了工具,可以在解决方案中创建一个测试,然后找到我没有为你提供测试的元素,例如点击页面上的一个链接,利用这些知识,然后看着它运行!
一如既往,如果您有任何问题,或希望我扩展本文的任何内容,请随时与我联系!
干杯
Sean