#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. Большое спасибо за ответ, но у меня все еще есть проблемы со статическими членами. Я добавил подробности к своему вопросу.