Разделите функции и базовый тест на два файла cs

#c# #selenium

#c# #селен

Вопрос:

Я хочу создать глобальный файл cs для всех моих тестовых проектов, чтобы сохранить все мои константы и функции. Например, этот файл для разных тестов global.cs:

 namespace SeleniumTests
{ 
    Public class forAllTests
    {
        //....
        public void Login()
        { 
            wait.Until<IWebElement>((d) => { return d.FindElement(By.Id("login")); });
            driver.FindElement(By.Id("login")).SendKeys("login");
            wait.Until<IWebElement>((d) => { return d.FindElement(By.Id("password")); });
            driver.FindElement(By.Id("password")).SendKeys("password");
        }
    }
}
  

И, например, другой файл Program.cs

 namespace SeleniumTests
{ 
    Public class Test
    { 
        forAllTests.Login();
        //.....
    }
}
  

Это возможно или нет?

UPD.

Спасибо за ответы. Да, мне нужен более конкретный совет. Я делаю тесты для Firefox, Chrome и Safari. Я знаю о шаблоне объектов страницы и использую его. Например, некоторый код от меня. Вот немного кода (части 3* 4* — не работает и хочу исправить их, пожалуйста, помогите мне). Как это работает сейчас: 1 * Program.cs —

        using System;
        using System.Web;
        using System.Text;
        using System.Text.RegularExpressions;
        using System.Threading;
        using NUnit.Framework;
        using OpenQA.Selenium;
        using OpenQA.Selenium.Chrome;
        using OpenQA.Selenium.Safari;
        using OpenQA.Selenium.Firefox;
        using OpenQA.Selenium.Support.UI;
        using OpenQA.Selenium.Support.PageObjects;
        using System.Diagnostics;
        using System.Threading;
        using Microsoft.Office.Interop.Excel;
        using Excel = Microsoft.Office.Interop.Excel;
        using System.Web;
        using System.Linq;
        using System.Windows.Forms;
        using System.IO;
        using System.Windows.Controls;





         namespace SeleniumTests
            {

                [TestFixture]
                public class Auth01
                {

                    private bool acceptNextAlert = true;
                    private LoginPage loginPage;
                    private PatientsPage patientsPage;        
                    private MainViewPage mainViewPage;
                    private EmkPage emkPage;
                    private IWebDriver driver;
                    private StringBuilder verificationErrors;
                    private string baseURL;                      
                    string drop_down_id;
                    string drop_down_text;
                    string url1;
                    string url2;
                    string now1;


                    [SetUp]
                    public void SetupTest()
                    {
                        driver = new FirefoxDriver();
                        driver.Manage().Timeouts().ImplicitlyWait(TimeSpan.FromSeconds(10));
                        baseURL = "http://....";
                        driver.Navigate().GoToUrl(baseURL   Constants.startUrl);
                        // driver.Manage().Window.Maximize();
                        loginPage = new LoginPage();
                        PageFactory.InitElements(driver, loginPage);
                        verificationErrors = new StringBuilder();

                    }


                     public void login()
                    {
                        WebDriverWait wait = new WebDriverWait(driver, TimeSpan.FromSeconds(10));
                        loginPage.Login.Clear();
                        loginPage.Login.SendKeys("login");
                        loginPage.Password.Clear();
                        loginPage.Password.SendKeys("password");
                        IWebElement myDynamicElement = wait.Until<IWebElement>((d) => { return d.FindElement(By.CssSelector(loginPage.enterbuttonPublic)); });
                        loginPage.EnterButton.Click();
                    }

        public void drop_down()
                    {
                        IWebElement elem = driver.FindElement(By.Id(drop_down_id));           
                        var options = elem.FindElements(By.TagName("option"));
                        string opt;
                        string value;
                        string x;
                        foreach (IWebElement option in options)
                        {

                            opt = option.Text;
                            value = option.GetAttribute("value");
                            if (drop_down_text.Equals(opt))
                            {
                                x = "//select[@id='"   drop_down_id   "']/option[@value='"   value   "']";

                            }
                        } 
                    }



                    [TearDown]
                    public void TeardownTest()
                    {
                        try
                        {
                            driver.Quit();
                        }
                        catch (Exception)
                        {

                        } Assert.AreEqual("", verificationErrors.ToString());
                    }

                    [Test]
                    public void The0Auth01Test()
                    {
                        Stopwatch stopWatch = new Stopwatch();
                        stopWatch.Start();
    login();
                     //.....
    drop_down_id="id";
    drop_down_text = "text";
    drop_down();
    //...
    stopWatch.Stop();
    } 
 static void Main()
        {

            Auth01 Auth01_1 = new Auth01();
            Auth01_1.SetupTest();
            Auth01_1.The0Auth01Test();
        }
  

2* AllAuth.cs — // для всех тестов

 using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using OpenQA.Selenium;
using OpenQA.Selenium.Firefox;
using OpenQA.Selenium.Chrome;
using OpenQA.Selenium.IE;
using OpenQA.Selenium.Support.UI;
using OpenQA.Selenium.Support.PageObjects;
using System.IO
;


namespace SeleniumTests
{

 public class LoginPage
    {



        private IWebDriver driver;
        const string login = "USERNAME";  
        public string loginPublic = login;
        [FindsBy(How = How.Id, Using = login)]  
        public IWebElement Login { get; set; }
        const string password = "PASSWORD";  
        public string passwordPublic = password;
        [FindsBy(How = How.Id, Using = password)]  
        public IWebElement Password { get; set; }
        const string enterbutton = "button.button-gray"; 
        public string enterbuttonPublic = enterbutton;
        [FindsBy(How = How.CssSelector, Using = enterbutton)]
        public IWebElement EnterButton { get; set; }
        const string notification = "#notification-message";  
        public string notificationPublic = notification;  
         [FindsBy(How = How.CssSelector, Using = notification)]
        public IWebElement Notification { get; set; }
        const string body = "BODY";    
        public string bodyPublic = body;
        [FindsBy(How = How.CssSelector, Using = body)]
        public IWebElement Body { get; set; }

        public LoginPage() { }

        public LoginPage(IWebDriver driver)
        {
            this.driver = driver;


            if (!driver.Url.Contains("http:..."))
            {
                throw new StaleElementReferenceException("This is not the login page");
            }
            PageFactory.InitElements(driver, this);
        }

    }
  

3* И я мечтаю о:

AllAuth.cs —

 ///...
namescpace SeleniumTests 
{
/////.....
public class Fantasy
{
 private IWebDriver driver;
login()
{
//....
}
drop_down()
{
//...
}
}
}
  

4* Program.cs —

 ///...
    namescpace SeleniumTests 
    {
    /////.....
 [Test]
                    public void The0Auth01Test()
                    {
fantasy.login();
fantasy.drop_down();
}
///...
}
  

Комментарии:

1. Для этого используется шаблон объектов страницы.

Ответ №1:

Уверен, что это возможно. Selenium — это просто API, доступ к которому осуществляется через WebDriver.dll для управления браузером. Для этого можно легко использовать любую структуру кодирования, которую вы хотите использовать. Я сделал 7-слойную версию для компании и видел, как многие просто записывают все это в 1, 2 или 3 слоя.

Вопрос в том, что лучше для вашей организации. Например … если вы используете определенную платформу UnitTest, тогда все ваши «тесты» будут существовать в проекте модульного тестирования и ссылаться на ваши основные функции, аналогичные уровню API. Я бы рекомендовал, по крайней мере, включить это, поскольку повторяющийся код для общих элементов управления в вашем приложении действительно плохо влияет на удобство обслуживания и лучшие практики.

вышесказанное относится к слоям, а не к файлам. Если у вас всего 5 тестов, это действительно непрактично и сложно поддерживать, пытаясь поместить все в один или два файла. Я бы действительно рекомендовал использовать общие стандарты кодирования и практики для выполнения тестов Selenium, точно так же, как обычный код c #. Приведенные ниже ссылки предназначены для c #, поскольку они помечены как c #.

Соглашения об именовании:http://msdn.microsoft.com/en-us/library/ff926074.aspx

Рекомендации по фреймворку:http://msdn.microsoft.com/en-us/library/ms229042.aspx

Руководство по стандартам:http://blogs.msdn.com/b/brada/archive/2005/01/26/361363.aspx

Многие другие, если вы загуглите…Если вам нужен более конкретный совет, пожалуйста, добавьте больше деталей к вашему вопросу, которые указывают, что это за проект, сколько тестов, особенности типа веб-приложения и сколько разных типов браузеров поддерживаются, поддерживает ли он мобильные устройства, использование базы данных, размер команды и т.д…Все это влияет на хороший дизайн

ОБНОВЛЕНИЕ: Похоже, вы на правильном пути, но вам нужно будет настроить свой драйвер и передать его функциям … или использовать общедоступную / защищенную переменную, одинаковую для всех. То, как у вас это сейчас, выглядит так, как будто он запускает новый драйвер каждый раз, когда вы вызываете отдельную функцию / метод, который, конечно, не будет работать.

Поэтому поместите свою настройку в начало тестового файла (# 3) с единственным методом тестирования в (# 4) в «настройка». При вызове первого теста (# 4) программа установки создаст экземпляр вашего драйвера и сохранит его в (#3). Затем передайте эту переменную драйвера во все ваши функции на (# 3-> # 2), чтобы они выполнялись на одном экземпляре драйвера. Фактический вызов setup должен быть в (# 3), но вызывается аналогично с fantasy.setup(); из (# 4). Аналогично, когда вы обновляете свой объект page, вы передаете в него существующий драйвер и перезаписываете существующий объект page новым объектом page … если вы не хотите сохранить кучу разных страниц…следите за использованием памяти. Это позволит вашим методам вообще не беспокоиться об обработке драйвера. Это также позволит вам запустить несколько потоков тестирования, и каждый из них будет поддерживать свои собственные драйверы. Затем, когда вы вызываете fantasy.login(); он перейдет к этому методу в (# 3) и вызовет метод (# 2) и передаст частный драйвер из памяти в (# 3) в (# 2) метод для целей выполнения.

Пожалуйста, дайте мне знать, если это непонятно…

Комментарии:

1. Привет, потрясающий ответ. Я умирал от желания найти какую-нибудь информацию о том, как выложить мой тестовый фреймворк. Я просто хочу немного больше разъяснений к тому, что я должен искать в Google, чтобы получить больше информации. «Методы разработки Selenium Automation Test Framework»?

2. Нет, поиск в Google был для стандартов кодирования c #, хотя вы могли бы что-нибудь найти. Честно говоря, диапазон фреймворков чрезвычайно широк. Я бы рекомендовал предоставить много специфики для вашей организации / приложения, а затем получить предложения. Я каждый раз разрабатываю его на заказ … хотя обычно есть как минимум два уровня … 1 для тестов и один для общих функций. У вас может быть уровень данных, уровень ошибок, слой карты, веб-слой, если вы этого хотите, слой результатов для более надежных результатов и т.д. … Много вариантов.

3. Итак, стоит отметить, что я никогда не собирал.. что-нибудь существенное. Это мое первое предприятие, не связанное со сценариями. Вот суть этого: я использую платформу на основе Selenium для автоматизации собственных мобильных приложений ( Appium ). Прямо сейчас у меня есть примерно .. 4 слоя? Универсальные классы для моделирования фактического пользовательского интерфейса — так что кнопки / метки / веб-просмотры — тогда у меня есть пользовательские реализации каждого из этих классов, которые содержат screen или viewcontroller. Этот слой обрабатывает действия, выполняемые в представлении. Следующий уровень объединяет действия и проверяет, происходит ли правильная вещь.

4. После этого у меня есть тестовый набор (я использую unittest на Python), который проходит через уровень action validation и упорядочивает их в том порядке, в котором они должны выполняться. Моя самая большая проблема заключается в том, что я никогда не делал и не видел успешной реализации фреймворка автоматизации, подобного этому. Я не знаю, имеет ли смысл то, что я делаю, или придерживается каких-либо рекомендаций. Я не знаю, смогу ли я отправить вам электронное письмо или два, но я хотел бы получить некоторые рекомендации. Мой адрес электронной почты указан в описании моего профиля.

5. Большое спасибо за ответ, но у меня все еще есть проблемы со статическими членами. Я добавил подробности к своему вопросу.