当前位置: 首页 > 知识库问答 >
问题:

Selenium-最佳实践-页面对象模式

张献
2023-03-14

我从0开始开发我的项目已经1年了。我的框架和测试已经达到了一定的“维护”水平。然而,每天我都在怀疑我是否在我的项目中使用了良好的实践。如果有经验的人能回答我的几个问题就好了。我主要对页面对象模式和页面工厂有疑问。

简要说明:

我的项目是一个基于一页的应用程序,用C#,angular编写。js,javascript。驱动程序是一个静态实例,它有很多额外的方法(在下面的代码中,我只展示了2)。每个页面都是在Pages类中初始化的静态实例。由于上述原因,我不必初始化Tests类中的对象。

问题列表:

>

  • 这是在页面中初始化静态实例的好方法。反恐精英?在我看来,当我以这种方式进行测试时,[测试]更容易重新定义。

    使用PageObject库的“真正”优势是什么?只有变量的命名?“[FindsBy(How=How.Id)]”?

    使用PageFactory的“真正”进步是什么?因为我没有找到任何或我的项目,它是无用的。

    在我的实际项目中,我有一个基类,子类从中继承,所有子类的通用方法都是用PageBase编写的。反恐精英。所以我没有重复代码的问题。

    现在我已经在每个页面中实现了单例,因此它与下面代码中使用的appraoch类似(区别只是初始化PageObject的方式)

    #region Signleton
    private static StartPage instance;
    
    private StartPage()
    {
    }
    
    public static StartPage Instance
    {
        get
        {
            if (instance == null)
            {
                instance = new StartPage();
            }
    
            return instance;
        }
    }
    #endregion
    

    单例实例

    StartPage.Instance.Search();
    

    方法的概念:

    浏览器反恐精英

    using OpenQA.Selenium;
    using OpenQA.Selenium.Chrome;
    
    namespace SeleniumTestFramework
    {
        public static class Browser
        {
            public static IWebDriver Driver { get; set; }
            public static bool Initialised { get; set; }
    
            public static void Initialize()
            {
                string chromeDriverDirectory = @"C:\chromedriver_win32";
                Driver = new ChromeDriver(chromeDriverDirectory);
                Initialised = true;
            }
    
            public static void Quit()
            {
                Driver.Quit();
                Initialised = false;
            }
        }
    }
    

    登录页面。反恐精英

    using OpenQA.Selenium;
    
    namespace SeleniumTestFramework.Pages
    {
        public class LoginPage
        {
            private IWebElement screenLogin = Browser.Driver.FindElement(By.Id("onScreenLogin"));
    
            public void OpenLoginModal()
            {
                screenLogin.Click();
            }
        }
    }
    

    逻辑模型。反恐精英

    using OpenQA.Selenium;
    
    namespace SeleniumTestFramework.Pages
    {
        public class LoginPage
        {
            private IWebElement screenLogin = Browser.Driver.FindElement(By.Id("onScreenLogin"));
    
            public void OpenLoginModal()
            {
                screenLogin.Click();
            }
        }
    }
    

    开始age.cs

    using OpenQA.Selenium;
    
    namespace SeleniumTestFramework.Pages
    {
        public class StartPage
        {
            private IWebElement surenameInput = Browser.Driver.FindElement(By.CssSelector(".id_surname_startpage_testId + input"));
            private IWebElement searchButton = Browser.Driver.FindElement(By.CssSelector(".search-button.search-customer"));
    
    
            public void Search()
            {
                surenameInput.SendKeys("1");
                searchButton.Click();
            }
        }
    }
    

    Pages.cs

    namespace SeleniumTestFramework.Pages
    {
        public static class Pages
        {
            public static LoginPage LoginPage
            {
                get
                {
                    var loginPage = new LoginPage();
                    return loginPage;
                }
            }
    
            public static LoginModal LoginModal
            {
                get
                {
                    var loginModal = new LoginModal();
                    return loginModal;
                }
            }
    
            public static StartPage StartPage
            {
                get
                {
                    var startPage = new StartPage();
                    return startPage;
                }
            }
        }
    }
    

    测验。反恐精英

    using NUnit.Framework;
    using SeleniumTestFramework;
    using SeleniumTestFramework.Pages;
    using OpenQA.Selenium.Support.PageObjects;
    using System.Threading;
    
    namespace SeleniumTest
    {
        [TestFixture]
        public class Tests
        {
            [SetUp]
            public void Before()
            {
                if (!Browser.Initialised) Browser.Initialize();
                Browser.Driver.Navigate().GoToUrl("http://localhost:8080/client/");
            }
    
            [TearDown]
            public void After()
            {
                Browser.Quit(); 
            }
    
            [Test]
            public void Test_without_static()
            {
                LoginPage loginPage = new LoginPage();
                loginPage.OpenLoginModal();
    
                LoginModal loginModal = new LoginModal();
                loginModal.Login();
    
                StartPage startPage = new StartPage();
                startPage.Search();
            }
    
            [Test]
            public void Test_with_static()
            {
                Pages.LoginPage.OpenLoginModal();
                Pages.LoginModal.Login();
                Pages.StartPage.Search();
            }
        }
    }
    
  • 共有1个答案

    冯淳
    2023-03-14

    有很多要讨论的。让我们开始吧。

    >

    PageObject框架的真正优点是将特定于页面的信息隔离在一个地方。这使得查找和维护这些信息变得简单。跨页通用的代码可以放在辅助程序或模块文件中。此公共代码不绑定到任何页面的细节,因此当WebElement的findElement(By)更改时,此公共代码不会受到影响。你想一想,不这样做简直是疯了。

    PageFactory有三个部分。前两个是在页面特定类中定义的。它们是@FindBy实例,用于定义如何访问在该页面上定义的有用的WebElements。这些是第一位的,这使得它们很容易找到和维护。接下来是定义为方法的受支持的测试人员操作。这些方法使用@FindBy实例,这使得它们不受FindBy实例更改的影响。

    public class HomePage { 
      final WebDriver driver;
    
      @FindBy(how = How.NAME, using = "text") private WebElement helloText;
      @FindBy(how = How.NAME, using = "exit") private WebElement exitButton;
    
    public HomePage(WebDriver driver) {
      this.driver = driver;
    }
    
    public void clickExitButton() {
      exitButton.click();
    }
    

    }

    3(续)。现在,在实际的测试脚本(Cucumber中的步骤定义文件)中,通过首先使用PageFactory初始化页面实例,然后调用针对该页面实例定义的测试操作方法来调用这些操作。所以

    public class HomePageExitTest extends TestCase {
      WebDriver driver;
    
      @Before public void setUp() throws Exception {
        driver = new FirefoxDriver();
      }
    
      @Test public void testHomeExit() throws Exception {
        driver.get("yoursite.com");
        HomePage homePage = PageFactory.initElements(driver, HomePage.class);
        homePage.clickExitButton();
      }
    
      @After public void tearDown() throws Exception {
        driver.quit();
      }
    }
    

    请参见本教程http://www.intexsoft.com/blog/item/34-selenium-webdriver-page-object-pattern-and-pagefactory.html

     类似资料:
    • 在Java页面对象模型中创建步骤时实例化对象的最佳方法是什么? 有人知道Cucumber脚本是如何编译的吗? 我想,如果一切都建成并符合要求,下面的第二个或第三个选项可能是最好的方法。 如果只编译与正在执行的测试相关的步骤,那么我想这将是第一个。 我举了以下例子: 以上所有步骤(在同一个LoginSteps.java类中加上更多)从以下开始 这是最好的方法,还是创建单个实例更好? 或者在Login

    • 问题内容: 按照目前的情况,这个问题不适合我们的问答形式。我们希望答案会得到事实,参考或专业知识的支持,但是这个问题可能会引起辩论,争论,民意调查或扩展讨论。如果您认为此问题可以解决并且可以重新提出,请访问帮助中心以获取指导。 7年前关闭。 我想了解更多有关如何使用Selenium IDE和RC创建良好的自动化测试的信息。是否有人对共享信息感兴趣。或讨论这个?特别适用于: 1)什么是组织UI测试的

    • 我希望一些帮助处理一个奇怪的边缘案例与我正在构建的一个分页API。 与许多API一样,这个API分页了大量的结果。如果查询/foos,将得到100个结果(即foo#1-100),以及一个指向/foos?page=2的链接,该链接将返回foo#101-200。 不幸的是,如果在API使用者进行下一个查询之前从数据集中删除了foo#10,/foos?page=2将抵消100并返回foos#102-20

    • 这里有些给使用和编写 Ansible playbook 的贴士. 你能在我们的 ansible-example repository.找到展示这些最佳实践的 playbook 样例.(注意: 这些示例用的也许不是最新版的中所有特性,但它们仍旧是极佳的参考.) Topics 最佳实践 接下来的章节将向你展示一种组织 playbook 内容方式. 你对 Ansible 的使用应该符合你的需求而不是我们

    • 处理后台任务与常规调用方法有很大的不同。本指南旨在帮助让您的后台任务平稳有效地运行。本文基于 这篇博客文章。 使任务参数小而简单 方法(任务)在调用之前会被序列化。使用 TypeConverter 类将参数转换为 JSON 字符串。如果您有复杂的实体和 / 或大对象; 包括数组,最好将它们放入数据库,然后只将其标识 (id) 传递给后台任务。 错误例子: public void Method(En

    • VR设计 VR设计不同于平面体验设计。作为一种新的媒介,有新的最佳实践需要遵循,特别是保持用户的舒适性和存在性。这在如下指南中已经写得很透彻了: Oculus VR最佳实践 Leap Motion VR最佳实践指南 一些值得注意的事情: 公共的金科玉律是永远不要意外地把相机控制权从用户手中剥夺。 单位(比如对于位置)应该考虑使用米(m)。这是因为WebVR API以米为单位返回姿势数据,进而传送给