Денис Чернилевский: Генерация тестовых данных....

48

Upload: yandex

Post on 16-Jun-2015

914 views

Category:

Documents


2 download

DESCRIPTION

Один из неотъемлемых этапов тестирования любых приложений — подготовка тестовых данных. Существует ряд систем, для которых данные крайне важны, так как от них зависит поведение всей системы. Например, так устроены системы биллинга, ERP-системы или система медийной рекламы Яндекса. И в таких случаях подготовка тестовых данных становится довольно сложной и масштабной задачей. В своем докладе я расскажу об одном из возможных подходов к решению этой проблемы и представлю нашу библиотеку ObjectBuilders. Она облегчает разработку автотестов и позволяет легко генерировать разнообразные данные для тестируемых систем. Библиотека ObjectBuilders — это проект с открытым исходным кодом, что даёт каждому возможность использовать её для своих нужд.

TRANSCRIPT

Page 1: Денис Чернилевский: Генерация тестовых данных. Библиотека ObjectBuilders
Page 2: Денис Чернилевский: Генерация тестовых данных. Библиотека ObjectBuilders

Чернилевский Денис Ведущий инженер по автоматизации тестирования

ObjectBuilders: генерация данных

Page 3: Денис Чернилевский: Генерация тестовых данных. Библиотека ObjectBuilders

Немного о нас

•  Команда: несколько десятков человек QA+Dev

•  Тестируем систему медийной рекламы

•  Server side приложения + базы данных

•  Python + PyTest

Page 4: Денис Чернилевский: Генерация тестовых данных. Библиотека ObjectBuilders

Подготовка тестовых данных

Проблема

Page 5: Денис Чернилевский: Генерация тестовых данных. Библиотека ObjectBuilders

Проблема

Рекламная кампания:

~30 Х ~15 + связи + еще 20-30 объектов для доп. конфигурации!

объектов параметров

Page 6: Денис Чернилевский: Генерация тестовых данных. Библиотека ObjectBuilders

Поддержка  

Независимость  

Прозрачность  Перезапуск  

Требования

Page 7: Денис Чернилевский: Генерация тестовых данных. Библиотека ObjectBuilders

7

Много подходов

Существующие данные

Page 8: Денис Чернилевский: Генерация тестовых данных. Библиотека ObjectBuilders

8

Много подходов

Вручную подготовить данные

Page 9: Денис Чернилевский: Генерация тестовых данных. Библиотека ObjectBuilders

9

Много подходов

Всякие Pairwise и Random

Page 10: Денис Чернилевский: Генерация тестовых данных. Библиотека ObjectBuilders
Page 11: Денис Чернилевский: Генерация тестовых данных. Библиотека ObjectBuilders

11

Много подходов

Паттерны Builder и Composite

Page 12: Денис Чернилевский: Генерация тестовых данных. Библиотека ObjectBuilders

Builder pattern

Конструирование   Представление  

Page 13: Денис Чернилевский: Генерация тестовых данных. Библиотека ObjectBuilders

Builder pattern

Builder   Интерфейс   Объект  

Создание объектов через удобный интерфейс класса

Page 14: Денис Чернилевский: Генерация тестовых данных. Библиотека ObjectBuilders

НО!

Page 15: Денис Чернилевский: Генерация тестовых данных. Библиотека ObjectBuilders

Недостаток: Класс Builder Composite

+ методы интерфейса

Page 16: Денис Чернилевский: Генерация тестовых данных. Библиотека ObjectBuilders

Builder pattern наизнанку J

ObjectBuilders

Page 17: Денис Чернилевский: Генерация тестовых данных. Библиотека ObjectBuilders

17

Данные =

набор объектов +

связи

Page 18: Денис Чернилевский: Генерация тестовых данных. Библиотека ObjectBuilders

18

Набор связанных объектов =

граф

Page 19: Денис Чернилевский: Генерация тестовых данных. Библиотека ObjectBuilders

Графы сильно совпадают

Page 20: Денис Чернилевский: Генерация тестовых данных. Библиотека ObjectBuilders

Описываем свойства графа! (а не объектов)

Page 21: Денис Чернилевский: Генерация тестовых данных. Библиотека ObjectBuilders

Универсальный инструмент!

Page 22: Денис Чернилевский: Генерация тестовых данных. Библиотека ObjectBuilders

Реализация и использование ObjectBuilders

2 уровня: •  Constructs – управление связями

•  Modifiers – управление модификациями

2 типа модификаторов: •  InstanceModifiers – модификация объектов

•  ConstructModifiers – модификация связей

Page 23: Денис Чернилевский: Генерация тестовых данных. Библиотека ObjectBuilders

Фабрика автомобилей

Пример

Page 24: Денис Чернилевский: Генерация тестовых данных. Библиотека ObjectBuilders

Базовая конфигурация

Кастомизация

+

Фабрика автомобилей

Page 25: Денис Чернилевский: Генерация тестовых данных. Библиотека ObjectBuilders

Объектная модель #Шасси сlass Chassis: type = CHASSIS_LIGHT #Двигатель class Engine: type = ENGINE_PETROL volume = 1.6 #Колесо class Wheel: radius = 15 type = WHEEL_STAMPED #Кузов сlass Body: type = BODY_SEDAN number = ???

Page 26: Денис Чернилевский: Генерация тестовых данных. Библиотека ObjectBuilders

Объектная модель Не хватает связей и некоторых параметров!

chassis = Chassis() wheels = [Wheel() for _ in xrange(4)] engine = Engine() body = Body() … chassis.wheels = wheels chassis.engine = engine engine.chassis = chassis chassis.body = body body.number = random() …

Page 27: Денис Чернилевский: Генерация тестовых данных. Библиотека ObjectBuilders

Эту задачу решают Constructs

Page 28: Денис Чернилевский: Генерация тестовых данных. Библиотека ObjectBuilders

Constructs

class Collection(typeToBuild, number=1)

class Unique(typeToBuild)

class Reused(typeToBuild, local=False, keys=[])

class Maybe(construct)

class Random(start=1, end=100500, pattern=None)

class Uplink()

Page 29: Денис Чернилевский: Генерация тестовых данных. Библиотека ObjectBuilders

Объектная модель #Шасси сlass Chassis: type = CHASSIS_LIGHT engine = Unique(Engine) body = Unique(Body) wheels = Collection(Wheel, number=4) transmission = Reused(Transmission) #Двигатель class Engine: type = ENGINE_PETROL volume = 1.6 transmission = Reused(Transmission)

Page 30: Денис Чернилевский: Генерация тестовых данных. Библиотека ObjectBuilders

Объектная модель

#Колесо class Wheel: radius = 15 type = WHEEL_STAMPED transmission = Reused(Transmission) #Кузов сlass Body: type = BODY_SEDAN number = Random() spoiler = Maybe(Unique(Spoiler))

Page 31: Денис Чернилевский: Генерация тестовых данных. Библиотека ObjectBuilders

Создаем автомобиль! (в базовой комплектации)

from builders.builder import Builder

car = Builder(Chassis).build()

Page 32: Денис Чернилевский: Генерация тестовых данных. Библиотека ObjectBuilders

Создаем автомобиль

То есть: •  Был создан объект типа Chassis •  Были созданы связанные объекты •  Объект Spoiler НЕ создан

Page 33: Денис Чернилевский: Генерация тестовых данных. Библиотека ObjectBuilders

Создаем автомобиль

Тип объекта car – Chassis. Поэтому: >>>car.engine.volume 1.6 >>>car.wheels[0].radius 15 >>>car.body.spoiler None

Page 34: Денис Чернилевский: Генерация тестовых данных. Библиотека ObjectBuilders

Но это базовая модификация!

Page 35: Денис Чернилевский: Генерация тестовых данных. Библиотека ObjectBuilders

Изменение графа

Модификаторы

Page 36: Денис Чернилевский: Генерация тестовых данных. Библиотека ObjectBuilders

Модификаторы

•  class InstanceModifier(classToRunOn) –  def thatSets(self, **kwargs) –  def thatDoes(self, action)

•  class Enabled(what)

•  class Given(construct, value)

•  class HavingIn(what, *instances)

•  class NumberOf(what, amount)

•  class OneOf(what, *modifiers)

Page 37: Денис Чернилевский: Генерация тестовых данных. Библиотека ObjectBuilders

Модификаторы: пример 1 Модификатор InstanceModifier() Хотим автомобиль с дизельным 6-литровым двигателем

big_diesel = InstanceModifier(Engine)\ .thatSets(type=ENGINE_DIESEL, volume=6.0)

car = Builder(Chassis).withA(big_diesel).build()

Page 38: Денис Чернилевский: Генерация тестовых данных. Библиотека ObjectBuilders

Модификаторы: пример 1 Модификатор InstanceModifier()

То же самое можно сделать через InstanceModifier.thatDoes()

def make_big_engine(engine): engine.type = ENGINE_DIESEL engine.volume = 6.0

big_diesel = InstanceModifier(Engine)\ .thatDoes(make_big_engine)

Page 39: Денис Чернилевский: Генерация тестовых данных. Библиотека ObjectBuilders

Модификаторы: пример 2 Модификатор Enabled() Хотим автомобиль со спойлером!

spoiler_option = Enabled(Body.spoiler)

car = Builder(Chassis).withA(spoiler_option).build()

>>>car.body.spoiler is not None

True

class Body:

spoiler = Maybe(Unique(Spoiler))

Page 40: Денис Чернилевский: Генерация тестовых данных. Библиотека ObjectBuilders

Модификаторы: пример 3 Модификатор NumberOf() Хотим 6 колес и тяжелую платформу!

six_wheels = NumberOf(Chassis.wheels, 6)

car = Builder(Chassis).withA(six_wheels).build()

>>>len(car.chassis.wheels) == 6

True

>>>car.chassis.type == CHASSIS_HEAVY

True

class Chassis:

wheels = Collection(Wheel, number=4)

Page 41: Денис Чернилевский: Генерация тестовых данных. Библиотека ObjectBuilders

Модификаторы: пример 4 Переиспользование модификаторов Хотим мощный вездеход с большим кузовом и кучей колес!

rover = [six_wheeled, big_diesel] + \ [InstanceModifier(Body).thatSets(type=BODY_HEAVY)]

rover = Builder(Chassis).withA(rover).build()

Page 42: Денис Чернилевский: Генерация тестовых данных. Библиотека ObjectBuilders

Что мы имеем и зачем все это надо? J

Итог

Page 43: Денис Чернилевский: Генерация тестовых данных. Библиотека ObjectBuilders

Итог: плюсы

Легкость + читаемость

Page 44: Денис Чернилевский: Генерация тестовых данных. Библиотека ObjectBuilders

Итог: плюсы

Тесты  • Создание  данных  • Логические  проверки  

Данные  • Объектная  модель  • Модификаторы  

Test  Framework  

• PyTest  • DB  и  API  клиенты  и  т.д.  

Page 45: Денис Чернилевский: Генерация тестовых данных. Библиотека ObjectBuilders

Итог: минусы

• Сложные модели • Copy-paste • Незаметные ошибки

Page 46: Денис Чернилевский: Генерация тестовых данных. Библиотека ObjectBuilders
Page 47: Денис Чернилевский: Генерация тестовых данных. Библиотека ObjectBuilders

Больше тестов -> больше модификаторов! 3 плюса: •  Переиспользование •  Понимание •  Упрощение поддержки

Page 48: Денис Чернилевский: Генерация тестовых данных. Библиотека ObjectBuilders

Спасибо!

Денис Чернилевский

http://bit.ly/objectbuilders

[email protected]