All streams
Search
Write a publication
Pull to refresh
2
0
Send message

Спасибо. А почему не рассматривали вариант решить эту задачу через, например, Allure TestOps и строить дашборды и статистику там ?

А где вы храните тест кейсы ?

Нам нужны не тестировщики в общем смысле, а, скорее, профессионалы в написании кодов по автотестам.

Золотые слова. А то из каждого утюга, что тестирование это просто, жми на кнопку и получай 300к

Может попросить тестировать/писать тесты разработчиков ?)

«Модульных тестов всегда больше, чем тестов с других уровней.»

Почему ?

Для чего тестировщику (особенно начинающему) знать Android Studio, XCode ?

Я выше писал, поддерживал ~5к апи тестов с различными версиями. Сначала тоже делал абстракции на абстракцию, потом все сильно упрощал, т.к. чем больше кода, тем сложнее стало в нем разбираться и метод "в лоб", сильно упростил написание и сопровождение тестов.

Мне трудно представить, что бы тот же фронт, например, писали в лоб, без использования MVC (не берем в расчет библиотеки) - на выходе будет неподдерживаемая каша. Но у вас в фирме приняли такое решение, это работает, ок)

Предлагалось, как вы ниже и написали, использовать задавание урла в 1 месте. В вашем же примере данной статьи, вы показываете о задании в каждом тесте/инициализации клиента.

Статья не про "куда нам деть url" ) Код в статье можно и нужно улучшать, но я бы начал с архитектуры, а потом думал об  url

Чтобы что? Боитесь, что requests надо будет заменять?

Я не хочу показаться грубым или надменным и заранее извиняюсь, но когда я писал эту статью, мне с одной стороны казалось, что я буду писать про очевидные вещи, даже несмотря на то, сколько кода я видел в проде автотестеров. Но нет, я получил хороший, полезный и интересный отклик)

Но вы ведь его повторяете в своих тестах (в репозитории) описывая свои модели и у вас появляется теперь 2 вещи, где описана структура ответов от API и в случае проблемы, какой из реализаций доверять больше?

Например, в сваггере могут не описать 400 ошибки (и их модели) или копипастнуть. Если бы мой код лежал в одной репе с бэком(на питоне), то я просто бы забрал модели и переиспользовал бы их.

Первоначальный тест читаемее в 10 раз итогового варианта.

У вас получился какой-то java подход с какими-то не нужными абстракциями (фабриками)

Как я писал выше, попробуйте мыслить не 1 тест, а "у нас тут много тестов и это все надо поддерживать"

Зачем выделять в отдельную сущность регистрацию, если в 99% случаев мы напишем на этот кусочек кода 5 тестов и никогда больше к нему не вернемся? (в API тестах, как по мне, page object подход не работает абсолютно, он только создает кучу ненужного кода, раскиданого по всему проекту)

А как вы предлагаете решить проблему? Писать в лоб? Где та тонкая грань, когда тестов "много" (больше 5?) и стоит писать нужный код и раскидывать по всему проекту

Зачем делать custom_request, но при этом все равно явно передавать ему url? У вас URL сервера не меняется на протяжении тестов, передайте его при инициализации.

Так как в будущем вы будете использовать эти тесты в CI и вам надо будет прокидывать url через командную строку и/или переменную. Поэтому хардкодить не вариант

Зачем каждой сущности типа Register, создавать своего клиента? http клиент должен быть 1 на весь прогон тестов (также, как и коннекты к базе и т.п.)

"Так же хотелось бы отметить, что код ниже про архитектуру, некоторые вещи я намерено упрощаю, что бы не затягивать."

Здесь реализация через фикстуру и "должен быть 1 на весь прогон тестов", как пример

Зачем вообще нужен custom_request и свой клиент, если они под собой используют все равно requests? Если хочется свои обработки, то лучше у requests кастомную сессию определить

инверсия зависимости

Зачем делать свою ResponseModel, если она не модель и повторяет ответы от requests? Если назвали моделью, то хоть минимальную валидацию данных в ней реализуйте

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

Вы упомянули swagger, но никак его не используете, зачем упомянули? По хорошему, на основе схемы надо реализовывать валидацию структуры и типов данных

Используем, сваггер это "книга данных", к в которую автотестор постоянно заглядывает и смотрит. В идеальной компании такой подход, когда мы доверимся полностью сваггеру и будем на основе его писать модели, сработал бы. Но я никогда не встречал "идеальный" сваггер, который 100% отражает действительность. Сваггер для меня это внешняя зависимость, а такие зависимости стараются убирать.

Как и написал выше, есть зависимость от проекта. На своем проекте мне пришлось выключить его, придётся переписывать фикстуры, изменился бэк. В соседней репе все работает прекрасно.

Если внутри команды есть договоренность, что этот уровень может использоваться в тестах (например, что бы чистить базу полбе себя или делать дополнительные проверки), то норм)

ну... если уйти от стереотипов, то aqa это разработчик. Разработчик обязан тестировать свой код. Если необходимо, то автотестер пишет "тесты на тесты" (на функции), просто это не так часто встречается

Я не думаю, что 10 строчек кода раздует проект )

Разработчики, при написании кода , используют паттерны, подходы, mvc и так далее. И делают они это не для того, что бы раздуть сроки, а для читаемого, гибкого кода и возможности быстро и безболезненно делать рефакторинг (да, это не гарантия, но всё же). Чем aqa “хуже”? Почему автотестер должен писать код в лоб, не думаю наперёд ?

Ничем не хуже, это такой же разработчик. Правильный построенный код (фронт, бэк, тесты) упрощает поддержку кода. Обычно команды тестирования, которые не могут это сделать/не хватает опыта и пишут «как есть», приводят проект к раздуванию и удорожанию (так как такие тесты легче выкинуть, чем поддерживать).

вы message на строгое соответствие проверяете. Например в мультиязычном приложении, такие сообщения иногда выносятся в отдельные файлы, доступные для правки не только программистами. Не думаю что тесты должны падать, только из за того что переводчик решил изменить формулировку сообщения. 

Это очень специфичная ситуация, когда в респонсе ответы мультиязычные, такое бывает не часто, это не может быть причиной что бы не проверять текстовки в ответе.

А проверять нужно и падать обязательно, так как одно дело, когда разработчик поменяет текстовику, а другое, когда вместо текста у вас пролезет стектрейс Java/scala/js и вы сможете отловить ошибку заранее.

Да, абсолютно верно, сваггер всегда должен быть актуальным.
На своих проектах я не могу использовать такие генераторы клиентов, мне все равно пришлось бы руками много писать

Всё равно не пойму зачем выносить стабильный и всем понятный requests куда то и заменять его каким то custom_client

На самом деле можно и не выносить и оставить как есть. И во многих примерах/документациях так. Но если по правильному - то выносить. Опять же сошлюсь на PO, так как он более менее знаком большинству - base_page для чего он? Ведь есть понятный и стабильный selenium. И когда вы ответите на этот вопрос, то будет понятен финт с requests.

Во первых именования — уже отмеченный response.response

Да, соглашусь, можно было более четче разделить именование, что бы не было путаницы

и почему body получается из объекта RegisterUser — магия сплошная

Не совсем понял ваш вопрос, класс RegisterUser отвечает за рандом данных для отправки регистрации пользователя. Да, его можно и нужно переписать и улучшить, но статья не про это.

Ну и проверка message на мой взгяд лишняя — лучше http код проверять.

Тут с вами сильно не соглашусь, проверка респонса обязательна

Такие абстракции каждый пишет по своему и каждый раз это как новый фреймворк(может быть хороший), который надо изучить, но по которому нет документации

Из моей практики происходит наоборот. За счет абстракций код хорошо читается и новый человек в команда достаточно быстро начинает писать тесты, смотря на верхнеуровневые примеры, постепенно погружаясь ниже.
П.C. документация у нас есть и она обязательна)

Так requests надо скрывать или нет? И зачем?

Задам встречный вопрос - для чего в PageObject используют base_page? Какую проблему это решает? Или можно в пейджах оставить методы селениума/плейврайта?

Иначе, как правильно заметили выше, все эти абстракции над абстракциями будут только мешать ещё не стабилизировавшемуся 

Это никак не связано, на каком этапе проект, стабилизировалось или нет, а вот код в лоб практически сразу становится сложно поддерживать. Код, который я показал, пытается решить эту проблему на старте проекта

 А скрывать requests, из за страха его будущей замены, я бы не стал ещё дольше — бессмысленная трата ресурсов. 

requests скрывается не из за "страха его будущей замены", условная будущая замена это пример, для чего мы это делаем, а не "молча выделим новую абстракцию". Вынести запросы в отдельный файл (кстати, почему это бессмысленная трата ресурсов?) это инверсия зависимостей.

Так же хотелось бы отметить, что код ниже про архитектуру, некоторые вещи я намерено упрощаю, что бы не затягивать.

Основная цель статьи это вопрос архитектуры

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

Да, лучше дописывать строку, что бы коллеге было больше информации, если упадем, то мы в любом случае словим "питоновские ошибки", но с пайтестам нам подсветят дифф

E       AssertionError: assert 'User created successfully.' == 'User created successfully.1'
E         - User created successfully.1
E         ?                           -
E         + User created successfully.

Инициализация клиента внутри тестового класса - не знаю, может и есть в этом что-то, но что если мы напишем другой клиент? Или у нас есть экземпляры клиента для разных случаев? И зачем вообще каждому тестовому классу свой клиент?

Где инициализировать клиента это второй вопрос, это не было целью статьи

Тестовый класс и его метод без докстринги ( то что там урл написан ясности что в нём проверяется не даёт). Чтобы понять, что делает тест, надо читать код, лезть под капот, тратить время.

Можно сделать так

    def test_registration(self):
        """
        Steps
        1. Try to register new user
        2. Check, that status code is 201
        3. Check response
        """
        body = RegisterUser.random()
        response = Register(url=URL).register_user(body=body, schema=valid_schema)
        assert response.status == 201
        assert response.response.get('message') == 'User created successfully.'
        assert response.response.get('uuid')

В статье рассматривался один тест, сценарий его оговаривался, поэтому код был дан без докстрингов, но в следующий раз учту, спасибо

Тестовая функция не принимает аргументов, значит нельзя её параметризировать, значит отпадает здоровый кусок функционала, который нам предоставляет PyTest. Если мы захотим сделать отрицательный тест, нам надо будет либо копипастить тестовую функцию, либо выносить параметры, чтобы их можно было перебирать через pytest.mark.parametrize

не совем понял вашего замечания. Параметризация в pytest работает не так, как вы описали, аргументы добавляются после использования декоратора @pytest.mark.parametrize(...)

Когда дело дойдёт до запуска, эти тесты надо будет либо списком вызывать, либо по файлам распихивать, что одно что другое неудобно. Поэтому существую маркеры.

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

Знаю, что мои замечания больше про большой проект, но всё же когда показываешь пример, надо или говорить что это автотест на один эндпоинт или уже показывать как масштабировать. Этот код не подходит для серьёзного проекта ( хотя бы потому что не используется питест)

Повторюсь, что эта статья не про pytest, pytest здесь использован только как ранер

Хоть автор и пишет, что он абстрагируется, толку от выноса импорта особо нет, поменять импорт при переходе на другую библиотеку - самое малое, что нужно будет сделать. Хочешь сделать на асинхронной либе - ну сделай сразу (хотя зачем, если есть xdist - непонятно).

xdist это не решение проблемы. Все зависит от проекта, но при "тысячах" тестах впихнуть xdist та еще задача.
Попробуйте мыслить категориями "у меня здесь 10 000 тестов и как мне с этим жить" )

По поводу переиспользования тестов с помощью фейкера - ну частично решает проблему, но гарантий уникальности не даёт. 

Если нужна уникальность, то обычно делают так

def random_email() -> str:
    """
    Get random email
    """
    timestamp = pendulum.now().int_timestamp
    return f"{timestamp}_{fake.email()}"

А для переиспользования тестов существуют фикстуры, которые сначала создают для теста нужные сущности а после себя чистят. После теста должен остаться только артефакт - отчёт или лог. А у вас база данных будет в куче пользователей.

В самом начале я написал, что пишем без фикстур) Так как это бы только бы отвлекало.

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

Как только ваши тесты переваливают за условную цифру в 100 тестов, то подход "пишем в лоб" и "все подробности торчат наружу" становится губительным для проекта тестов, поддерживать такой код становится невозможно.

А если на проекте всё постоянно меняется, то при наличии этих абстракций, количество мест где надо что-то где-то поправить только увеличится.

Ровно наоборот и происходит)

Information

Rating
Does not participate
Registered
Activity