Рубрики
Без рубрики

Flask REST API -PART: 6- Тестирование API

Часть 6: Тестирование API для отдыха Привет! В предыдущей части серии мы узнали, как на … помеченные Python, колбу, тестированием, отдыхом.

Часть 6: Тестирование API для отдыха

Привет! В предыдущей части серии мы узнали, как выполнить сброс пароля в нашем API для отдыха.

В этой части мы собираемся учиться, как проверить конечные точки API для отдыха.

Почему мы должны проводить время письма?

  • Чтобы убедиться, что наше приложение не нарушается при внесении изменений/рефакторинга
  • Автоматизировать повторяющиеся ручные тесты, уменьшающие человеческие ошибки
  • Быть в состоянии освободить до производства по пятницам;)
  • Тестирование обеспечивает лучший рабочий процесс CI/CD.

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

Когда дело доходит до тестирования, есть два самых популярных инструмента для тестирования приложений Python. 1) Неизвестный : Неизвестный это питон Стандартная библиотека Это означает, что он распространяется с Python. Неизвестный Обеспечивает тонны инструментов для построения и беговых испытаний.

2) pteest : pteest это библиотека Python, которую мне нравится звонить, является сумеретом Неизвестный Это означает, что вы можете запустить тесты, написанные в Неизвестный с pteest Отказ Это облегчает писать тесты и быстрее.

В этом руководстве мы собираемся научиться писать тесты, используя Неизвестный , потому что он позволяет нам написать наши тесты, используя Ооп Отказ

Прежде чем начать, снимите строку ниже приложение

app.config['MONGODB_SETTINGS'] = {
    'host': 'mongodb://localhost/movie-bag'
}

и добавлять

MONGODB_SETTINGS = {
    'host': 'mongodb://localhost/movie-bag'
}

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

Прежде всего, давайте создадим env Файл Чтобы сохранить наши тестовые конфигурации, мы должны отделить наши тестовые конфиги с наших конфиг разработки и производства.

В корневом каталоге создайте файл .env.test и добавьте к нему следующие конфиги.

touch .env.test
#~/movie-bag/.env.test

JWT_SECRET_KEY = 'super-secret'
MAIL_SERVER: "localhost"
MAIL_PORT = "1025"
MAIL_USERNAME = "support@movie-bag.com"
MAIL_PASSWORD = ""
MONGODB_SETTINGS = {
    'host': 'mongodb://localhost/movie-bag-test'
}

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

Теперь давайте создадим новую папку Тесты Внутри нашего корневого каталога. Создайте новый файл __init__.py внутри Тесты Папка, также создайте новый файл test_signup.py Отказ

mkdir tests
cd tests
touch __init__.py
touch test_signup.py
#~/movie-bag/tests/test_signup.py

import unittest
import json

from app import app
from database.db import db


class SignupTest(unittest.TestCase):

    def setUp(self):
        self.app = app.test_client()
        self.db = db.get_db()

    def test_successful_signup(self):
        # Given
        payload = json.dumps({
            "email": "paurakh011@gmail.com",
            "password": "mycoolpassword"
        })

        # When
        response = self.app.post('/api/auth/signup', headers={"Content-Type": "application/json"}, data=payload)

        # Then
        self.assertEqual(str, type(response.json['id']))
        self.assertEqual(200, response.status_code)

    def tearDown(self):
        # Delete Database collections after the test is complete
        for collection in self.db.list_collection_names():
            self.db.drop_collection(collection)

Пойдем шаг на шаг, чтобы понять, на самом деле происходит.

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

Настройка () Способ выполняется каждый раз перед запуском каждого метода, определенного на Подписчик класс. Настройка () Как следует из названия, используется для настройки нашей тестовой инфраструктуры перед запуском тестов. Здесь вы можете увидеть, что мы определяем this.app и this.db В этом методе. Мы используем app.test_client () вместо приложение Потому что он облегчает тестирование нашей колбе. Кроме того, мы получаем наши База данных экземпляр с db.get_db () и установить это на this.db Отказ

Точно так же test_successful_signup () это метод, который на самом деле тестирует Регистрация особенность. Здесь мы определили полезную нагрузку, которая должна быть JSON ценность. И мы отправляем Пост Запрос на /API/AUTH/регистрация .

Ответ из запроса используется, чтобы наконец утверждать, что наши Регистрация Функция фактически отправляла идентификатор пользователя и успешный код состояния, который является 200 Отказ

Наконец, после каждого тестовых методов Обзор () Способ работает каждый раз. Этот метод отвечает за очистку нашей установки инфраструктуры. Это включает в себя удаление нашей коллекции базы данных для Тестовая изоляция Отказ

Тестовая изоляция

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

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

Перед запуском нашего первого теста обязательно экспортируйте переменную среды Env_file_location с расположением к файлу Test Eng.

Чтобы установить это значение Mac/Linux может запустить команду:

export ENV_FILE_LOCATION=./.env.test

и Windows пользователь может запустить команду:

set ENV_FILE_LOCATION=./.env.test

Убедитесь, что вы активировали вашу виртуальную среду с помощью Pipenv Shell Отказ

Для запуска теста введите эту команду в вашем терминале.

python -m unittest tests/test_signup.py

Вы должны быть в состоянии увидеть такое вывод:

.
----------------------------------------------------------------------
Ran 1 test in 1.023s

OK

Это означает, что наш тест успешно работает.

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

Как вы можете видеть, нам понадобится этот Настройка () и Обзор () в нашем Ever Testcase. Итак, давайте переместим эту логику в новый файл, давайте назовем это BaseCase.py Отказ

#~/movie-bag/tests/BaseCase.py

import unittest

from app import app
from database.db import db


class BaseCase(unittest.TestCase):

    def setUp(self):
        self.app = app.test_client()
        self.db = db.get_db()


    def tearDown(self):
        # Delete Database collections after the test is complete
        for collection in self.db.list_collection_names():
            self.db.drop_collection(collection)

Теперь обновите свой test_signup.py выглядеть так:

 import json

-from app import app
-from database.db import db
+from tests.BaseCase import BaseCase

-
-class SignupTest(unittest.TestCase):
+class SignupTest(BaseCase):
-
-    def setUp(self):
-        self.app = app.test_client()
-        self.db = db.get_db()

     def test_successful_signup(self):
         # Given
...
-
-    def tearDown(self):
-        # Delete Database collections after the test is complete
-        for collection in self.db.list_collection_names():
-            self.db.drop_collection(collection)

Теперь давайте добавим тест для нашего Вход Особенность, создайте новый файл test_login.py внутри тесты папка со следующим кодом.

#~/movie-bag/tests/test_login.py

import json

from tests.BaseCase import BaseCase

class TestUserLogin(BaseCase):

    def test_successful_login(self):
        # Given
        email = "paurakh011@gmail.com"
        password = "mycoolpassword"
        payload = json.dumps({
            "email": email,
            "password": password
        })
        response = self.app.post('/api/auth/signup', headers={"Content-Type": "application/json"}, data=payload)

        # When
        response = self.app.post('/api/auth/login', headers={"Content-Type": "application/json"}, data=payload)

        # Then
        self.assertEqual(str, type(response.json['token']))
        self.assertEqual(200, response.status_code)

Здесь мы впервые создали пользователь с /api/auth/fightup Конечная точка и вход в систему, используя одинаковую электронную почту и пароль и утверждать, что /API/AUTH/Вход Конечная точка возвращает токен.

Теперь давайте добавим тесты, чтобы проверить создание фильма. Создать test_create_movie.py с кодом ниже.

#movie-bag/tests/test_create_movie.py

import json

from tests.BaseCase import BaseCase

class TestUserLogin(BaseCase):

    def test_successful_login(self):
        # Given
        email = "paurakh011@gmail.com"
        password = "mycoolpassword"
        user_payload = json.dumps({
            "email": email,
            "password": password
        })

        self.app.post('/api/auth/signup', headers={"Content-Type": "application/json"}, data=user_payload)
        response = self.app.post('/api/auth/login', headers={"Content-Type": "application/json"}, data=user_payload)
        login_token = response.json['token']

        movie_payload = {
            "name": "Star Wars: The Rise of Skywalker",
            "casts": ["Daisy Ridley", "Adam Driver"],
            "genres": ["Fantasy", "Sci-fi"]
        }
        # When
        response = self.app.post('/api/movies',
            headers={"Content-Type": "application/json", "Authorization": f"Bearer {login_token}"},
            data=json.dumps(movie_payload))

        # Then
        self.assertEqual(str, type(response.json['id']))
        self.assertEqual(200, response.status_code)

Чтобы запустить все тесты одновременно использовать команду:

python -m unittest --buffer

Здесь --buffer или -b используется для отказа от выхода на успешной прогон.

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

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

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

Я не включал эти тесты в сам учебник, но я обязательно вспомню их в репо Github.

Вы можете найти весь код, который мы написали до сих пор и Больше тестов здесь

Что мы узнали из этой части серии?

  • Почему мы должны написать тесты для нашего приложения
  • Какая тестовая изоляция и почему мы должны изолировать наши тесты случаи
  • Как тестировать колбу отдыха API с модульный тест

Не стесняйтесь добавлять все, что мне не хватает в этой статье о комментариях ниже.

Если у вас есть какие-либо тематические предложения, пожалуйста, дайте мне знать. Я надеюсь увидеть вас в следующем.

До тех пор вы можете следовать за мной на твиттер

Оригинал: “https://dev.to/paurakhsharma/flask-rest-api-part-6-testing-rest-apis-4lla”