Есть небольшой опыт использования selemium, pytest, nosetests, behave
Вы не могли бы привести пример небольшого, с вашей точки зрения, эталонного микрофреймворка для тестирование?
Пример - любой сайт имеет шапку, меню и подвал - элементы, которые одинаковы на каждой странице.
Подскажите, как построить паттерн pageobject используя только selenium и например pytest, без сторонних библиотек.
Пример - локаторы находятся в отдельном файле locators.py (вообще можно ли так?), описание страницы (pageobject) в отдельном файле pageobject.py, тесты в отдельном файле test.py, настройка драйвера (или как это правильно называется) в отдельном файле common.py.
Для примера можно хоть 1 поле с 1 кнопкой сделать.
Я очень хочу разобраться, но везде уже столько на*уеверчено, всяких сторонних библиотек и прочего мусора. Мне бы увидеть основы и разобраться в них. Если кто-то может помочь буду вам очень благодарен.
А вы не подскажите, что такое фикстуры и что такое инстансы? Я правильно понимаю, что инстанс это некоторое состояние, а фикстура это состояние фиксирует.
Например нам нужно тестировать поиск - что будет фикстурой, а что будет инстанс?
Фикстура это просто фиксация состояния, а состояние это например - браузер chrome, размер окна maximize_window и т.д.?
Фикстура - это декоратор, декоратор - это например функция, которая принимает на вход (функцию, класс, метод, любой объект, хотя если речь идет об изменении его то immutable не подойдут)(короче это паттерн) ± переменные и выдает какой то результат, при желание можно подробней ознакомится что такое декоратор. В контексте тестов мы создаем функция декорируя её фикстурой:
и в каждом тесте мы просто юзаем фикстуру browser получая инстанс нужого нам драйвера (соответственно передав нужный параметр --browser chrome в строку запуска теста). Обрамляя функцию в фикстуру заменяет аналоги beforeTest, beforeClass, beforeMethod прекондишенов например в Java. Фикстура проделает свою работу перед началом теста и если нужно то и после теста, в документации всё есть!
На счет инстанса в контексте питона, то в питоне инстанс это ВСЁ)) это экземпляр, в питоне всё является объектом. Чтобы говорить о инстансе (в питоне) нужно понимать вообще его объектную модель. так что к тестам это не имеет в данном случае ни какого отношения, если я правильно понял суть вопросов выше))))
Мне кажется вы правильно поняли мой вопрос. Спасибо. А как могли бы выглядеть фикстуры например для таких сценариев:
Мы тестируем логин форму посты - позитивный сценарий. Предусловие - мы не залогинены. Вводим в поля логин и пароль, жмем кнопку “Вход”. Ожидаемый результат - заголовок страницы сменился на “Входящие письма”.
Мы тестируем логин форму, кнопку выхода из аккаунта. Предусловие - пользователь залогинен под (тестовые входные данные). Нажимаем кнопку “Выход”. Ожидаемый результат - получаем nitification “Вы вышли из аккаунта”.
Короче я в рамках обучения решил реализовать тестирование формы логина, а затем какой-нибудь пользовательский сценарий - например вход в почту и отправка письма через почтовый сервис mail.ru.
В первую очередь необходимо создать базовый файл с базовым классом, я назвал его base.py но мне кажется это какое-то неверное название.
Этот пример я тут на форуме нашел.
Класс SeleniumWrapper это обертка для одного состояния. Оно запускает вебдрайвер chrome в полное окно и переходит на страницу mailru
from selenium import webdriver
class SeleniumWrapper:
_instance = None
def __new__(cls, *args, **kwargs):
if not cls._instance:
cls._instance = super(SeleniumWrapper, cls).__new__(cls, *args, **kwargs)
return cls._instance
def connect(self, host="https://mail.ru/"):
self.driver = webdriver.Chrome()
self.driver.maximize_window()
self.base_url = host
return self.driver
Но я все равно не до конца въезжаю. Что например такое _instance = None и функция def new
Смотрите. Я написал тест в одном файле. Я так делал раньше, но раньше я еще использовал библиотеку unittest и nosetests. Я хочу разобраться именно в связке чистого pytest и чистого selenium на основе паттерна проектирования тестов PageObject. Помогите пожалуйста мне запустить данный тест, а так разнести все данные, как этого требуется для паттерна.
Разнести я имею ввиду, что судя по описаниям и представлениям, есть некий файл в котором хранятся только элементы страницы и методы связанные с этими элементами, а в других файлах пишутся только тестовые сценарии, а в третьем настройки самого вебдрайвера, инстансов и фикстур (вот тут я пока не понимаю о чем говорю, хотя стараюсь).
test_login.py
import unittest
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
hostname = 'https://mail.ru/'
login = 'fbs_test1203@mail.ru'
password = '1Passw0rd'
class MainPageMail(unittest.TestCase):
def setUp(self):
self.driver = webdriver.Chrome()
def the_login_test(self):
driver = self.driver
wait = WebDriverWait(driver, 100)
driver.get(hostname)
login_field = driver.find_element(By.XPATH, value="//input[@id='mailbox:login']")
password_field = driver.find_element(By.XPATH, value="//input[@id='mailbox:password']")
submit_button = driver.find_element(By.XPATH, value="//input[@value='Войти']")
wait.until(EC.element_to_be_clickable((login_field)))
login_field.send_keys(login)
wait.until(EC.element_to_be_clickable((password_field)))
password_field.send_keys(password)
wait.until(EC.element_to_be_clickable((submit_button)))
submit_button.click()
def tearDown(self):
self.driver.quit()
Запускается так nosetests test_login.py
Если запускаю через pytest то вообще ничего не работает.
Блин, я кажется начинаю понимать. В одном файле мы описываем отдельно ключевые объекты страницы - это могут быть кнопки, поля, ссылки и еще какие-то вещи. Каждая функция - это метод позволяющий обратиться к этому элементу.
Затем отдельно пишется файл с тестом. В этом файле используются как раз выше описанные методы для обращения к тому или иному элементу на странице. Выстраивание последовательных цепочек из этих методов - это и есть наши тестовые случаи или тестовые сценарии.
А вот что обычно еще за файл один, его еще common называют или типа того. Что там содержится.
Зачем наследоваться от unittest. Вы же используете pytest. И название класса должно быть с Test
TestMainPageMail. Вроде так…Могу ошибаться и файлик где код теста по-моему должен тоже быть вида test_mainpagemail- например и метод класса (TestMainPageMail) должен быть test_login
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
hostname = 'https://mail.ru/'
login = 'fbs_test1203@mail.ru'
password = '1Passw0rd'
class TestMainPageMail():
def setup_class(self):
self.driver = webdriver.Chrome()
def test_the_login(self):
driver = self.driver
wait = WebDriverWait(driver, 100)
driver.get(hostname)
assert "Mail.Ru" in driver.title
login_field = driver.find_element(By.XPATH, value="//input[@id='mailbox:login']")
password_field = driver.find_element(By.XPATH, value="//input[@id='mailbox:password']")
submit_button = driver.find_element(By.XPATH, value="//input[@value='Войти']")
login_field.send_keys(login)
password_field.send_keys(password)
submit_button.click()
def teardown_class(self):
self.driver.quit()
Блин, это какой-то все бред. Нет, я понимаю, что там что-то важное, но я читаю и ничерта не понимаю. Отвратительная документация. Я пробовал читать несколько раз и ничерта не понятно. Примеры бы хоть нормальные привели.
Короче пытаюсь переписать под pytest, но сталкиваюсь с тем, что нужно разнести селекторы и описание элементов и тесты в разные места. Натолкните на мысль пожалуйста, как быть?
Короче, благодаря тебе мой друг, мне удалось сделать свою первую фикстуру и сделать Первый простой тест. Я добавил туда неявные ожидания. Очень благодарен.
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
hostname = 'https://mail.ru/'
login = 'fbs_test1203@mail.ru'
password = '1Passw0rd'
"""
Тест на заполнение формы корректными данными. Тест является пройденным при проверке на наличии фразы "Входящие"
в заголовке Title после нажатия кнопки Войти.
"""
def test_input_login_password_correct(driver):
driver.get(hostname)
wait = WebDriverWait(driver, 10)
assert "Mail.Ru" in driver.title
login_field = driver.find_element(By.XPATH, value="//input[@id='mailbox:login']")
password_field = driver.find_element(By.XPATH, value="//input[@id='mailbox:password']")
submit_button = driver.find_element(By.XPATH, value="//input[@value='Войти']")
login_field.send_keys(login)
password_field.send_keys(password)
submit_button.click()
try:
element = wait.until(EC.title_contains("Входящие"))
finally:
assert "Входящие" in driver.title
Но вопрос остается открытым. Я все еще ищу примеры как вынести локаторы, желательно в отдельный класс отдельной страницы, желательно в отдельный файл) В общем не понимаю пока как организовать pageobject.