понедельник, 30 июля 2018 г.

pytest BVT часть 1

Поговорим немного о тестировании. Что такое Build Verification Test (BVT/БВТ)?

Найти общего определения на просторах интеренета мне не удалось, поэтому попробую свормулировать сам. 

BVT - это набор базовых тестовых сценариев, нацеленных на выявление явных ошибок. Часто в литературе также под BVT понимают Смок или Дымовое тестирование.

BVT обладают следующими свойствами:
  1. выполнение тестов производится на каждую сборку
  2. высокая скорость исполнение
  3. высокое покрытие базовой функциональности
  4. включают только критичные тестовые сценарии 
Оговорюсь здесь, что описанные выше свойства довольно условные, каждая команда вправе сама устанавливать критерии качества и расширать BVT до нужного ей объема.
Что все это значит для автоматизатора?

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

Примеры автоматических BVT.
  1. Проверка статусов запущенных сервисов.
  2. Наличие в сборке исполняемых и конфигурационных файлов.
  3. Отсутсвие критичных сообщений об ошибках в логах.
  4. и т.п. и т.д.
Разобравшись немного с BVT в следующих частях попробуем написать на pytest небольшой фремворк для разработки универсальных BVT.

воскресенье, 30 октября 2016 г.

Это определение идеально

Есть старый метод исследования систем. Он называется «метод черного ящика». Метод гласит: мы не знаем внутренней структуры системы, но мы можем подать сигнал на ее вход и зафиксировать реакцию на выходе. Сопоставляя определенными методами (методом спектрального анализа, методом решения определенных интегральных уравнений и так далее) функции на входе и выходе, мы можем получить характеристику системы.

вторник, 16 февраля 2016 г.

pytest продолжение

В первой части статей мы немного познакомились с основными базовыми возможностями pytest. Рассмотрели его особенностей и подходы.

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

Последовательно выполнение тестовых сценариев


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

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

Например, тестируемая программа при первом запуске накатывает схему базы (sqlite чтобы не морочиться) и заполняет её некоторой служебной информацией. Допустим перед нами стоит задача "дешево" протестировать этот модуль. Сходу задачу модно разбить на 2 подзадачи - проверка создания файла базы, затем проверка схемы и в конце проверка данных.

Самый простой вариант - нумерация в названии тестов

# conftest.py
import os
import pytest
import sqlite3


def pytest_configure(config):

    config.DB_PATH = "db.sqlite"


@pytest.fixture(scope="module")
def creator(request):
    DB_PATH = request.config.DB_PATH
    con = sqlite3.connect(DB_PATH)
    cur = con.cursor()
    cur.executescript("""
        create table person(
            firstname,
            lastname,
            age
        );

        create table book(
            title,
            author,
            published
        );

        insert into book(title, author, published)
        values (
            'Dirk Gently''s Holistic Detective Agency',
            'Douglas Adams',
            1987
        );
        """)
    con.commit()
    con.close()
    return DB_PATH


@pytest.fixture
def cursor(request):
    class cursor:

        def __init__(self, dbpath):
            self.dbpath = dbpath
            self.conn = sqlite3.connect(self.dbpath)

        def table_exists(self, table):
            cursor = self.conn.cursor()
            cursor.execute(
                "SELECT name FROM sqlite_master WHERE type = \"table\"")
            tables = cursor.fetchall()
            for each in tables:
                if table in each:
                    return True
            return False

        def getrows(self, table):
            cursor = self.conn.cursor()
            cursor.execute("SELECT * FROM %s;" % (table))
            return cursor.fetchall()

    return cursor(request.config.DB_PATH)

# test.py
def test_1_db_exists(creator):
    assert os.path.exists(creator)


@pytest.mark.parametrize("table", ["person", "book"])
def test_2_check_scheme(table, creator, cursor):
    result = cursor.table_exists(table)
    assert result


@pytest.mark.parametrize("table", ["book"])
def test_3_check_rows(table, creator, cursor):
    assert cursor.getrows(table)


Спасибо документации питона за готовые примеры.

У такого подхода есть ряд недостатков.
1. В названии теста появляется нумерация - это лишняя мета информация. (Это может сказаться на тестовом отчете или билд логе CI сервера)
2. Название теста усложняется
3. Вставка нового элемента в середину приведет к смене нумерации всех последующих тестов


Вариант посложнее - маркеры


Свои маркеры мы реализовывать не будем, а используем готовый плагин pytest-ordering. В принципе вся реализация такого плагина составит не больше 100 строчек кода.

# test.py
@pytest.mark.order1
def test_db_exists(creator):
    assert os.path.exists(creator)


@pytest.mark.order2
@pytest.mark.parametrize("table", ["person", "book"])
def test_check_scheme(table, creator, cursor):
    result = cursor.table_exists(table)
    assert result


@pytest.mark.order3
@pytest.mark.parametrize("table", ["book"])
def test_check_rows(table, creator, cursor):
    assert cursor.getrows(table)


Наши тестовые функции преобразились, стали более понимаемы для чтения.
Из коробки плагин содержит создание цепочек выполнения, более понятные маркеры (pytest.mark.run('first'), pytest.mark.run('second')) и прочее. Более подробно в микро доку плагина.

Ссылки
[1] https://docs.python.org/2/library/sqlite3.html
[2] http://pytest-ordering.readthedocs.org/en/develop/

суббота, 6 февраля 2016 г.

Топ 10 вопросов по python на stackoverflow

What does the yield keyword do in Python?
What is a metaclass in Python?
How to check whether a file exists using Python
Does Python have a ternary conditional operator?
Calling an external command in Python
How can I make a chain of function decorators in Python?
What does `if __name__ == “__main__”:` do?
How can I merge two Python dictionaries in a single expression?
Sort a Python dictionary by value
How do I install pip on Windows?

Довольно ожидаемо

[1] stackoverflow.com