.NET项目web自动化测试实战——Selenium 2.0

简介: PS:这次用公司的项目来练手,希望公司不会起诉我,因为我绝对是抱着学习的态度,没有任何恶意。仅供交流学习。 该项目是基于SharePoint平台所开发的门户网站,为了切身感受一下Selenium 2.0我决定自己动手写一个自动化测试用例,而不是通过录制的方式,以加深我对一些web操作的理解。

PS:这次用公司的项目来练手,希望公司不会起诉我,因为我绝对是抱着学习的态度,没有任何恶意。仅供交流学习。

该项目是基于SharePoint平台所开发的门户网站,为了切身感受一下Selenium 2.0我决定自己动手写一个自动化测试用例,而不是通过录制的方式,以加深我对一些web操作的理解。

我设计的测试用例是:检查Staff Spotlight中所包含的item对应三级页面显示的信息是否正确。具体逻辑是,在英语浏览器下检查后台list中英语Column的value和三级page中对应Column的value是否一致,在日语浏览器下检查后台list中日语Column的value和三级page中对应Column的value是否一致,如果是英语浏览器下后台list中没有勾选“English Ready”项,则在三级page中显示日语Column的value。

三级page如下:

点击页面右上角的“Edit Item”按钮可以跳转到后台list中相应的item编辑页面;点击上方的“日本语”按钮可以进行英语和日语的语言切换,点击“日本语”将切换到日本语,再点击“English”将切换到英语。

我们本次要取的页面元素就是Department,Location,Title以及Join Date的页面value。然后点击“Edit Item”按钮跳转到后台item编辑页面,按“F12”,找到对应要获取的后台元素值:

获取到对应的Column的value所在页面的元素,然后获取页面上显示的值,将其与三级page上的value按我们之前说过的逻辑进行比对,如果一样,测试通过;如果不一样,测试失败。

代码如下:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using OpenQA.Selenium;
using OpenQA.Selenium.IE;
using OpenQA.Selenium.Support;
using OpenQA.Selenium.Support.UI;
using Selenium;
using mySelenium;
using System.Runtime.InteropServices;
using System.Threading;
using System.Diagnostics;
using System.Net;
using System.IO;
using System.Globalization;

namespace mySelenium
{
    class LoginSPSite
    {
        [DllImport("user32.dll", CharSet = CharSet.Auto, ExactSpelling = true)]
        public static extern IntPtr GetForegroundWindow();
        static void Main(string[] args)
        {
            IWebDriver driver = new InternetExplorerDriver();
            IWebDriver iw = login(driver,"https://insite.ccqa11apps.com/Pages/default.aspx");
            INavigation navi = iw.Navigate();
            string language = checkLanguage(iw);
            if (language == "English")
            {
                //Check the English page.(检查英语页面信息。)
                Console.ForegroundColor = ConsoleColor.Yellow;
                Console.WriteLine("--English page check--");
                checkPageInfo(iw,"En");
                //Turn to the Japanese page.(转换到日语页面。)
                navi.GoToUrl("https://insite.ccqa11apps.com/Pages/default.aspx");
                waitUntilPageLoaded(iw, "ctl00_ctl21_ToggleLanguage");
                iw.FindElement(By.Id("ctl00_ctl21_ToggleLanguage")).Click();
                //Check the Japanese page.(检查日语页面信息。)
                Console.ForegroundColor = ConsoleColor.Yellow;
                Console.WriteLine("--Japanese page check--");
                checkPageInfo(iw,"Ja");
            }
            //Language is "Japanese".
            else 
            {
                //Check the Japanese page.(检查日语页面信息。)
                Console.ForegroundColor = ConsoleColor.Yellow;
                Console.WriteLine("--Japanese page check--");
                checkPageInfo(iw,"Ja");
                //Turn to the English page.(转换到英语页面。)
                navi.GoToUrl("https://insite.ccqa11apps.com/Pages/default.aspx");
                waitUntilPageLoaded(iw, "ctl00_ctl21_ToggleLanguage");
                iw.FindElement(By.Id("ctl00_ctl21_ToggleLanguage")).Click();
                //Check the English page.(检查英语页面信息。)
                Console.ForegroundColor = ConsoleColor.Yellow;
                Console.WriteLine("--English page check--");
                checkPageInfo(iw, "En");
            }
        }//Get the 3rd page info.(从三级page中获取指定的Column的value,需要传入IWebDriver对象以及当前页面的语言种类。)
        private static void checkPageInfo(IWebDriver iw,string LanType)
        {
            //Check 3rd page with the format: "https://insite.ccqa11apps.com/_layouts/15/InSite/pages/StaffDetails.aspx?id=" under the English environment.
            INavigation navi = iw.Navigate();
            for (int i = 1; i <= 5; i++)
            {
                Console.ForegroundColor = ConsoleColor.White;
                Console.WriteLine("This is the " + i + " staff item check info:");
                navi.GoToUrl("https://insite.ccqa11apps.com/_layouts/15/InSite/pages/StaffDetails.aspx?id=" + i.ToString());
                var eles = iw.FindElements(By.ClassName("apps-staffdetail-content-splitline"));
                //Get the info from the 3rd page.(获取三级page上Column的value信息。)
                StaffSpotlight staffSpotlight = new StaffSpotlight();
                staffSpotlight.Department = eles[0].FindElement(By.ClassName("apps-staffdetail-content-splitline-bottom")).Text;
                staffSpotlight.Location = eles[1].FindElement(By.ClassName("apps-staffdetail-content-splitline-bottom")).Text;
                staffSpotlight.Title = eles[2].FindElement(By.ClassName("apps-staffdetail-content-splitline-bottom")).Text;
                staffSpotlight.JoinDate = eles[3].FindElement(By.ClassName("apps-staffdetail-content-splitline-bottom")).Text;
                //Find the "Edit Item" button.(找到“Edit Item”按钮并点击。)
                iw.FindElement(By.ClassName("apps-staffdetail-edit")).Click();
                //Wait until the element on page loaded.(等待页面元素加载完成。)
                waitUntilPageLoaded(iw, "Inpex_Department_$containereditableRegion");
                //Get the info from the backend list.(获取后台list中Column的value信息。)
                StaffSpotlight staffInfoFromBackend = new StaffSpotlight();
                staffInfoFromBackend.Department = iw.FindElement(By.Id("Inpex_Department_$containereditableRegion")).FindElement(By.ClassName("valid-text")).Text;
                staffInfoFromBackend.Location = iw.FindElement(By.Id("Inpex_Office_$containereditableRegion")).FindElement(By.ClassName("valid-text")).Text;
                //Job title is the title under English IE.(Title是日语浏览器中显示的Title,EnTitle是英语浏览器中显示的Title。)
                staffInfoFromBackend.Title = iw.FindElement(By.Id("Inpex_Job_Title_30756774-5931-4844-bac1-a2f463d04ca0_$TextField")).GetAttribute("value").ToString();
                staffInfoFromBackend.EnTitle = iw.FindElement(By.Id("Inpex_Job_Title_E_ef6d11a7-f73e-4885-bef1-527a1c03c924_$TextField")).GetAttribute("value").ToString();
                staffInfoFromBackend.JoinDate = iw.FindElement(By.Id("Inpex_Join_Date_b133dcfe-4e0c-4f0f-8b82-92a549516e6d_$DateTimeFieldDate")).GetAttribute("value").ToString();
                //Compare the actual 3rd info with the expected backend info.(将三级page中的Column value和预期value比较。)
                Compare("Department", staffSpotlight.Department, staffInfoFromBackend.Department);
                Compare("Location", staffSpotlight.Location, staffInfoFromBackend.Location);
          //英语页面的Title信息比对检查逻辑。
if (LanType == "En") { try { //If can get the element underneath, it means "English Ready" has been checked.(如果可以在页面上获取到该元素,说明“English Ready”这一项是勾选的。) string ifChecked = iw.FindElement(By.Id("Inpex_E_Text_a355a229-a1bb-48f5-81dd-e428a0d4fbd2_$BooleanField")).GetAttribute("checked").ToString(); Console.WriteLine("The Englisht ready has been checked: " + ifChecked); //Compare the title with the backend "En" one.(比对EnTitle和三级page中的Column value是否一致。) Compare("Title", staffSpotlight.Title, staffInfoFromBackend.EnTitle); } //If can not get the element by the ID above, it means "English Ready" has not been checked.(如果获取不到“English Ready”元素下的“checked” Attribute,说明没勾选。) catch(Exception ex) { WriteLog(ex); //Compare the title with the backend "Jp" one.(比对Title和三级page中的Column value是否一致。) Console.WriteLine("The Englisht ready has been checked: false"); Compare("Title", staffSpotlight.Title, staffInfoFromBackend.Title); } }
          //日语页面的Title信息比对检查逻辑。
else { staffInfoFromBackend.Title = iw.FindElement(By.Id("Inpex_Job_Title_30756774-5931-4844-bac1-a2f463d04ca0_$TextField")).GetAttribute("value").ToString(); Compare("JapTitle", staffSpotlight.Title, staffInfoFromBackend.Title); } //Change the time format into the same.(统一转换三级page上的join date时间格式以及后台list item的join date时间格式,并进行比较。) string joinDateOnPage; string joinDateFromBackend; if (staffSpotlight.JoinDate != "") { DateTime dt = Convert.ToDateTime(staffSpotlight.JoinDate); joinDateOnPage = dt.ToString("yyyy-MM-dd"); } else { joinDateOnPage = ""; } if (staffInfoFromBackend.JoinDate != "") { DateTime dt2 = Convert.ToDateTime(staffInfoFromBackend.JoinDate); joinDateFromBackend = dt2.ToString("yyyy-MM-dd"); } else { joinDateFromBackend = ""; } Compare("JoinDate", joinDateOnPage, joinDateFromBackend); } }      //Compare value method.(传入:对应要检查的Column的标题,三级page中Column的value,后台list中item对应Column的value。) private static void Compare(string title, string p1, string p2) { if (p1 == p2) { Console.ForegroundColor = ConsoleColor.Green; Console.WriteLine(title + " info on the 3rd page has passed the check."); } else { Console.ForegroundColor = ConsoleColor.Red; Console.WriteLine(title + "info on the 3rd page has not passed the check."); Console.WriteLine("The info on the 3rd page: " + p1); Console.WriteLine("The info from the backend page: " + p2); } } //Check language method.(检查当前页面所处于的语言环境,判断是英语还是日语,并返回当前语言种类。) private static string checkLanguage(IWebDriver iw) { string currentLanguage; //Wait until the element on page loaded. waitUntilPageLoaded(iw, "ctl00_ctl21_ToggleLanguage"); string language = iw.FindElement(By.Id("ctl00_ctl21_ToggleLanguage")).Text; if (language.Length == 3) { currentLanguage = "English"; return currentLanguage; } else { currentLanguage = "Japanese"; return currentLanguage; } } //Wait until loaded method.(等待网页加载完毕指定元素,如果没有加载完,获取不到,捕获异常,继续等待,直到指定元素加载完毕。) private static void waitUntilPageLoaded(IWebDriver iw, string element) { try { iw.FindElement(By.Id(element)); } catch (Exception ex) { WriteLog(ex); Thread.Sleep(2000); waitUntilPageLoaded(iw, element); } } //Login method.(登陆网站的方法,需要传入IWebDriver对象以及网站的url。) public static IWebDriver login(IWebDriver driver, string url) { INavigation navigation = driver.Navigate(); navigation.GoToUrl(url); driver.FindElement(By.Id("overridelink")).Click(); IntPtr myPtr = GetForegroundWindow(); //IntPtr hWnd = FindWindow(null, "abc"); if (myPtr != IntPtr.Zero) { //Send message to the window. System.Windows.Forms.SendKeys.SendWait("dswu"); System.Windows.Forms.SendKeys.SendWait("{TAB}"); System.Windows.Forms.SendKeys.SendWait("1qaz2wsxE"); System.Windows.Forms.SendKeys.SendWait("{ENTER}"); } return driver; } //Write log method.(将捕获到的异常打印到本地log文件中。) private static void WriteLog(Exception ex) { string logUrl = Environment.GetFolderPath(Environment.SpecialFolder.DesktopDirectory) + "\\SeleniumAutoTest.txt"; if (File.Exists(@logUrl)) { using (FileStream fs = new FileStream(logUrl, FileMode.Append)) { using (StreamWriter sw = new StreamWriter(fs, Encoding.Default)) { try { sw.Write(ex); } catch (Exception ex1) { WriteLog(ex1); } finally { sw.Close(); fs.Close(); } } } } else { using (FileStream fs = new FileStream(logUrl, FileMode.CreateNew)) { using (StreamWriter sw = new StreamWriter(fs, Encoding.Default)) { try { sw.Write(ex); } catch (Exception ex1) { WriteLog(ex1); } finally { sw.Close(); fs.Close(); } } } } } } }

这里我创建一个类,用来存储三级page以及后台list中获取到的Staff item的信息:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace mySelenium
{
    class StaffSpotlight
    {
        public string Department { get; set; }
        public string Location { get; set; }
        public string Title { get; set; }
        public string EnTitle { get; set; }
        public string JoinDate { get; set; }
    }
}

按F5进行测试,结果如下:

测试通过。

覆盖多浏览器在Selenium也是很容易实现的,只需要把IE打开方法改用为指定浏览器所对应的打开方法:

 IWebDriver driver = new InternetExplorerDriver(); 

把这句换了,之后的步骤对应做些修改即可。

自动化测试从某些方面讲确实是一劳永逸的,但是有很多时候自动化测试是完全没有必要的,尤其是项目周期很短的情况下,自动化的封装应该更偏向于具有普遍性的可复用过程,而不是业务逻辑。

有时候,产出决定付出。我们没必要为了一个两三月交付的项目写一堆自动化测试用例,否则得不偿失。自动化测试应该更偏向于长期上线、持续迭代的项目展开!否则最后失落感是一定有的。

 

请大家关注我的博客园,给我的文章点个赞!关注一个测试开发工程师的成长之路。

相关文章
|
1月前
|
JavaScript 前端开发 测试技术
使用Selenium执行JavaScript脚本:探索Web自动化的新领域
本文介绍了如何在Selenium中使用JavaScript解决自动化测试中的复杂问题。Selenium的`execute_script`函数用于同步执行JS,例如滑动页面、操作时间控件等。在滑动操作示例中,通过JS将页面滚动到底部,点击下一页并获取页面信息。对于只读时间控件,利用JS去除readonly属性并设置新日期。使用JS扩展了Selenium的功能,提高了测试效率和精准度,适用于各种自动化测试场景。
41 1
|
17天前
|
Web App开发 前端开发 Java
《手把手教你》系列技巧篇(九)-java+ selenium自动化测试-元素定位大法之By name(详细教程)
【4月更文挑战第1天】 这篇教程介绍了如何使用Selenium Webdriver通过name属性来定位网页元素,作为系列教程的一部分,之前讲解了id定位,后续还会有其他六种定位方法。文中以百度搜索为例,详细说明了定位搜索框(name=&quot;wd&quot;)并输入关键词“北京宏哥”的步骤,包括手动操作流程、编写自动化脚本以及代码实现。此外,还提供了查看和理解Selenium源码的方法,强调了`open implementation`选项用于查看方法的具体实现。整个过程旨在帮助读者学习Selenium的元素定位,并实践自动化测试。
38 0
|
29天前
|
Web App开发 存储 JavaScript
《手把手教你》系列技巧篇(八)-java+ selenium自动化测试-元素定位大法之By id(详细教程)
【2月更文挑战第17天】本文介绍了Web自动化测试的核心——元素定位。文章首先强调了定位元素的重要性,指出找不到元素则无法进行后续操作。Selenium提供八种定位方法,包括By id、name、class name等。其中,By id是最简单快捷的方式。文章还阐述了自动化测试的步骤:定位元素、操作元素、验证结果和记录测试结果。此外,讨论了如何选择定位方法,推荐优先使用简单稳定的方式,如id,其次考虑其他方法。最后,作者提供了Chrome浏览器的开发者工具作为定位元素的工具,并给出了通过id定位的代码示例。
51 0
|
13天前
|
前端开发 Java 测试技术
《手把手教你》系列技巧篇(十二)-java+ selenium自动化测试-元素定位大法之By link text(详细教程)
【4月更文挑战第4天】本文介绍了link text在自动化测试中的应用。Link text是指网页中链接的文字描述,点击可跳转至其他页面。文章列举了8种常用的定位方法,其中着重讲解了link text定位,并通过实例展示了如何使用Java代码实现点击百度首页的“奥运奖牌榜 最新排名”链接,进入相应页面。如果link text不准确,则无法定位到元素,这说明linkText是精准匹配,而非模糊匹配。文章还提到了partial link text作为link text的模糊匹配版本,将在后续内容中介绍。
35 4
|
11天前
|
XML 前端开发 Java
《手把手教你》系列技巧篇(十四)-java+ selenium自动化测试-元素定位大法之By xpath上卷(详细教程)
【4月更文挑战第6天】按宏哥计划,本文继续介绍WebDriver关于元素定位大法,这篇介绍定位倒数二个方法:By xpath。xpath 的定位方法, 非常强大。使用这种方法几乎可以定位到页面上的任意元素。xpath 是XML Path的简称, 由于HTML文档本身就是一个标准的XML页面,所以我们可以使用Xpath 的用法来定位页面元素。XPath 是XML 和Path的缩写,主要用于xml文档中选择文档中节点。基于XML树状文档结构,XPath语言可以用在整棵树中寻找指定的节点。
42 0
|
30天前
|
Web App开发 安全 Java
《手把手教你》系列技巧篇(七)-java+ selenium自动化测试-宏哥带你全方位吊打Chrome启动过程(详细教程)
【2月更文挑战第16天】本文介绍了如何通过查看源码理解Selenium启动Chrome浏览器的过程。首先,展示了启动Chrome的Java代码,包括设置系统属性、创建WebDriver实例、最大化窗口、设置隐性等待、打开网站、获取页面标题以及关闭浏览器。文章还讲解了包(package)、import导入、setProperty设置系统属性、WebDriver接口、driver实例、manage方法、get方法加载网页以及quit方法退出浏览器的基本概念和作用。适合没有Java基础的读者了解Selenium与Java的交互方式。
45 3
|
2天前
|
Java 测试技术 定位技术
《手把手教你》系列技巧篇(二十三)-java+ selenium自动化测试-webdriver处理浏览器多窗口切换下卷(详细教程)
【4月更文挑战第15天】本文介绍了如何使用Selenium进行浏览器窗口切换以操作不同页面元素。首先,获取浏览器窗口句柄有两种方法:获取所有窗口句柄的集合和获取当前窗口句柄。然后,通过`switchTo().window()`方法切换到目标窗口句柄。在项目实战部分,给出了一个示例,展示了在百度首页、新闻页面和地图页面之间切换并输入文字的操作。最后,文章还探讨了在某些情况下可能出现的问题,并提供了一个简单的本地HTML页面示例来演示窗口切换的正确操作。
24 0
|
3天前
|
敏捷开发 监控 前端开发
深入理解自动化测试框架Selenium的架构与实践
【4月更文挑战第16天】 在现代软件开发过程中,自动化测试已成为确保产品质量和加快迭代速度的关键手段。Selenium作为一种广泛使用的自动化测试工具,其开源、跨平台的特性使得它成为业界的首选之一。本文旨在剖析Selenium的核心架构,并结合实际案例探讨其在复杂Web应用测试中的高效实践方法。通过详细解读Selenium组件间的交互机制以及如何优化测试脚本,我们希望为读者提供深入理解Selenium并有效运用于日常测试工作的参考。
11 1
|
4天前
|
自然语言处理 测试技术 API
深入理解自动化测试框架Selenium的设计理念与实践
【4月更文挑战第15天】 在现代软件开发过程中,自动化测试已成为确保产品质量和加速迭代的关键手段。Selenium作为一种广泛使用的自动化测试框架,提供了对多种浏览器和平台的支持,极大地促进了Web应用的功能测试。本文旨在剖析Selenium的核心设计理念,探讨其在实际项目中的应用,并指出常见的误区及最佳实践,以期帮助测试工程师更高效地利用Selenium进行测试工作。
|
5天前
|
监控 测试技术 API
深入理解自动化测试框架Selenium的设计与实现
【4月更文挑战第14天】在软件开发过程中,自动化测试是确保代码质量、减少人工重复劳动的关键步骤。Selenium作为一款广泛使用的自动化测试工具,提供了对多种浏览器和操作系统的支持。本文将探讨Selenium的核心组件及其架构设计,分析其如何通过WebDriver与浏览器交互,以及它如何支持多种编程语言进行脚本编写。同时,我们还将讨论Selenium Grid的作用以及它如何实现并行测试,以缩短测试周期并提高测试效率。
169 58