Python для тестировщика: как маленькие скрипты c pandas помогают в тестировании больших наборов данных

от автора

Я работаю тестировщиком на проекте, суть которого состоит в сборе и хранении различных данных и формировании на их основе разных отчетов и файлов-выгрузок. При формировании таких отчетов учитывается большое количество условий для отбора данных и поэтому при тестировании приходится много работать с SQL-запросами в БД. Но для проверки правильности отбора данных и поиска лишних/пропавших данных этого зачастую не хваетает, поэтому пришлось искать дополнительные инструменты для этого.

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

Проектируем сценарий скрипта


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

Примерные шаги для сценария:

  1. Получаем файл с данными в таком-то формате (или несколько файлов)
  2. Получаем данные из файла/файлов
  3. Отбираем нужные данные
  4. Выполняем какие-то операции над данными
  5. Выгружаем данные в Excel-файл, если нужно (обычно такой формат самый удобный для дальнейшего анализа и хранения)

Затем нужно подумать о том, как и где можно получить входные данные. Это может быть вручную созданный файл с данными, выгрузка на UI данных в файл с учетом фильтров, файл с данными парсинга с помощью другого скрипта, файл выгрузки результатов SQL-запроса в БД (из БД можно быстро выгрузить данные в csv-файл), json-файл или xml-файл с данными из ответа на запрос к API и др.

Пишем скрипты на python с использованием pandas и других библиотек


Для написания скриптов на python нужно установить интерпретатор и подходящую IDE. Также лучше всего создать отдельную виртуальную среду под этот проект.

Для скриптов я использую разные библиотеки, какие-то из них являются встроенными библиотеками python, какие-то нужно устанавливать дополнительно:

  • pandas — библиотека для анализа данных. Она позволяет работать с данными из файлов разных форматов, а также получать данные сразу из БД с помощью SQL-запроса. Данные из файлов загружаются в дата-фреймы (визуально — те же таблицы, что и в Excel), с данными в которых уже можно выполнять разные операции: объединять данные из разных дата-фреймов по аналогии с join/union в SQL, выбирать нужные данные по определенным условиям, сравнивать данные в разных столбцах дата-фрейма и т.д.
  • openpyxl, xlrd — библиотеки для работы с Excel.

Простейший каркас скрипта для работы с данными из файлов формата csv, json, Excel выглядит следующим образом:

# Подключаем библиотеку pandas import pandas as pd  # Загружаем данные из csv-файла в дата-фрейм # (предварительно копируем файл с данными в папку со скриптом) # При экспорте данных из БД в csv-файл лучше всего использовать разделитель ";" df = pd.read_csv('./csv_file.csv', sep=';', encoding='utf-8')  # или # Загружаем данные из json-файла в дата-фрейм # (предварительно копируем файл с данными в папку со скриптом) # df = pd.read_json('./json_file.json', encoding='utf-8')  # или # Загружаем данные из Excel-файла в дата-фрейм, указав название листа в файле # (предварительно копируем файл с данными в папку со скриптом) # file_excel = 'Excel_file.xlsx' # df = pd.ExcelFile(file_excel).parse('Лист1')   # Выполняем какие-то операции с данными в дата-фрейме и  # загружаем их в дата-фрейм final_df   # Выгружаем данные в Excel-файл, если нужно # при этом указываем название для нового файла и название листа # (файл будет создан в папке со скриптом) writer = pd.ExcelWriter('Итог.xlsx') final_df.to_excel(writer, 'Лист1') writer.save() 

В этом скрипте данные из файла нужного формата загружаются в дата-фрейм, отбираются нужные данные и над ними выполняются какие-то операции, затем данные записываются в новый Excel-файл.

Если нужно работать с данными, полученными в результате SQL-запроса к БД, то можно не экспортировать их в csv-файл, а сразу получать их в дата-фрейм, выполняя SQL-запрос в БД в самом скрипте:

# Подключаем библиотеку pandas import pandas as pd # Подключаем библиотеку для работы с БД, например для работы с PostgreSQL # (если БД другая - ищем другую подходящую библиотеку) import psycopg2  # Создаем подключение к БД conn = psycopg2.connect(dbname='название_БД', host='хост', port='порт',                         user='пользователь', password='пароль')  # Указываем нужный SQL-запрос q = """select ...      from ...      where ..."""  # Загружаем данные в дата-фрейм, выполнив SQL-запрос df = pd.read_sql_query(q, conn)   # Выполняем какие-то операции с данными в дата-фрейме и  # загружаем их в дата-фрейм final_df   # Выгружаем данные в Excel-файл, если нужно # при этом указываем название для нового файла и название листа # (файл будет создан в папке со скриптом) writer = pd.ExcelWriter('Итог.xlsx') final_df.to_excel(writer, 'Лист1') writer.save() 

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

Когда данные получены в дата-фрейм, то их можно сразу объединить с данными из другого дата-фрейма (аналоги join или union в SQL) или выполнить над ними какие-то операции, например, удалить дубли, убрать строки с пустыми значениями в определенных ячейках, сравнить данные в нескольких столбцах, отобрать нужные строки/столбцы и т.д. Подробнее можно почитать в документации для pandas.

Варианты использования скриптов


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

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

Сценарий №1

Есть три файла в формате csv с данными. Для каждой строки с данными есть поле с уникальным идентификатором id. Данные из этих файлов отбираются с учетом определенных условий и заносятся в таблицу в БД, затем эти данные выводятся в отчете в виде таблицы на UI. Есть возможность выгрузки данных на UI в Excel-файл.

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

  • В файлах могут быть дубли по id, в отчете запись с одним и тем же идентификатором должна учитываться только один раз (при этом выбираем просто одну любую из строк с таким идентификатором из данных).
  • Строки с отсутствием данных в ячейке столбца reg_date не должны учитываться.
  • На самом деле условий отбора может быть больше, также данные могут сравниваться с уже имеющимися в системе данными и в отчет уже будут выводиться только пересекающиеся данные по id, но для примера будем учитывать только два условия, указанных выше.

Задача тестировщика: Проверить, что строки с нужными объектами корректно отобраны из файлов-исходников и все эти объекты выводятся в отчете на UI.

Составляем сценарий для скрипта:

  • Загружаем в дата-фреймы нужные данные из этих трех csv-файлов, объединяем данные в один дата-фрейм (по аналогии с union в SQL), удаляем строки с дублями по id, удаляем строки без данных в столбце reg_date.
  • Выгружаем на UI данные итогового отчета в Excel-файл, удаляем ненужные данные, загружаем данные из него во второй дата-фрейм.
  • Объединяем (merge) эти два дата-фрейма в один (по аналогии с outer join в SQL) по уникальному идентификатору и уже записываем полученные данные в Excel-файл для дальнейшего анализа.
  • Дальше уже открываем полученный файл и с помощью фильтров анализируем строки с данными и смотрим, что все строки, выбранные из файлов-исходников с учетом условий, есть в файле выгрузки данных отчета, полученном на UI.

В итоговом файле данные будут содержать только один столбец с идентификатором id, если названия у столбцов в разных дата-фреймах совпадали, и может быть не понятно, какие столбцы/строки из какого были файла. Поэтому я либо называю столбцы с уникальным идентификатором разными названиями в файлах, либо в каждый файл добавляю отдельный столбец «Строки из файла такого-то» и в нем проставляю значения «Да» — потом при анализе итогового Excel-файла удобно делать фильтрацию по этому столбцу, т.к. они всегда содержат значение и, фильтруя по ним, можно уже понять, какие данные расходятся в соответствующих столбцах.

Пример данных из файла example1_csv_1.csv:

Пример данных из файла report_UI.xlsx:

Скрипт на python выглядит следующим образом:

# Подключаем библиотеку pandas import pandas as pd  # Выбираем нужные столбцы из csv-файлов и загружаем в дата-фреймы # (в файле не должно быть столбцов с одинаковым названием) df_from_file1 = pd.read_csv('./example1_csv_1.csv', sep=';', encoding='utf-8',                             usecols=['id', 'name', 'email', 'reg_date']) df_from_file2 = pd.read_csv('./example1_csv_2.csv', sep=';', encoding='utf-8',                             usecols=['id', 'name', 'email','reg_date']) df_from_file3 = pd.read_csv('./example1_csv_3.csv', sep=';', encoding='utf-8',                             usecols=['id', 'name', 'email', 'reg_date'])  # Объединяем предыдущие три дата-фрейма в один новый дата-фрейм  # (по аналогии с union в SQL) df_from_csv = pd.concat([df_from_file1, df_from_file2, df_from_file3]).\     reset_index(drop=True) print(df_from_csv)  # Удаляем строки с дубликатами по указанному столбцу df_from_csv.drop_duplicates(subset='id', keep='first', inplace=True) print(df_from_csv)  # Удаляем строки со значением NaN (нет значения) для столбца reg_date df_from_csv = df_from_csv.dropna() print(df_from_csv)  # Загружаем данные из Excel-файла выгрузки с UI в дата-фрейм, # при этом указываем название листа в файле # (предварительно копируем файл с данными в папку со скриптом) file_excel = 'report_UI.xlsx' df_from_excel = pd.ExcelFile(file_excel).parse('Лист1') print(df_from_excel)  # Объединяем дата-фрейм с отобранными данными из файлов-исходников и # дата-фрейм с данными из файла выгрузки с UI # (по аналогии с outer join в SQL) df = df_from_csv.merge(df_from_excel, left_on='id', right_on="Номер", how='outer') print(df)  # Выгружаем данные в новый Excel-файл writer = pd.ExcelWriter('Итог.xlsx') df.to_excel(writer, 'Лист1') writer.save() 

Ограничения:

  • При работе с файлами с очень большим количеством строк придется разбивать их на отдельные файлы (тут нужно пробовать, у меня редко бывают файлы более 30 000 строк).
  • Часто в файлах (обычно формата Excel) от заказчиков/аналитиков могут быть данные с пробелами или другими невидимыми знаками в ячейках, в этом случае такие скрипты использовать не получится без чистки исходных данных.

Сценарий №2
В разделе есть данные в виде таблицы по определенным объектам из одного источника. Система будет получать данные из второго источника (интеграция) и обновлять этими данными существующие данные таблицы. Каждая запись в таблице – это данные по одному объекту, который имеет уникальный идентификатор. Если из нового источника данные объекта по идентификатору совпадают с данными уже существующего объекта – то все поля существующей записи обновляются данными из нового источника (подтверждаются). Если же в таблице еще нет объекта с идентификатором из второго источника – то в таблице создается новая запись с данными из нового источника. Данные из второй системы можно выгрузить заранее в json-файл.

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

Составляем сценарий для скрипта:

  • Выгружаем на UI данные из таблицы раздела в Excel-файл (если нет такой возможности, то всегда можно экспортировать данные из результата SQL-запроса, используемого в коде для вывода данных в эту таблицу на UI) и залить данные из него в первый дата-фрейм.
  • Получаем json-файл с данными из второго источника и загружаем их во второй дата-фрейм.
  • Объединяем данные (merge — по аналогии с outer join в SQL) из двух полученных дата-фреймов в один новый дата-фрейм по уникальному идентификатору и выгружаем данные из него в Excel-файл, по которому уже в будущем будет проводиться тестирование. В этом файле будет сразу видно, какие строки должны были обновиться в таблице раздела, а какие должны были добавиться вновь.

Ограничения:

  • При работе с файлами с очень большим количеством строк придется разбивать их на отдельные файлы (тут нужно пробовать, у меня редко бывают файлы более 30 000 строк).
  • Если в json-файле есть несколько уровней вложенности объектов/массивов данных – то из внутренних уровней они будут загружены в ячейку как объект/массив, поэтому работать без какой-либо подготовки с json-файлами с помощью pandas удобно только для данных без лишней вложенности объектов/массивов.

Сценарий №3

Выполняется запрос к API системы, в ответе на который приходят данные по объектам в формате json.

Задача тестировщика: Сравнить данные из ответа на запрос к API с данными из результата SQL-запроса в БД.

Составляем сценарий для скрипта:

  • Выполняем SQL-запрос в БД, экспортируем данные из результата запроса в csv-файл, загрузжаем эти данные в первый дата-фрейм.
  • Сохраняем данные из ответа на запрос к API в json-файл, загружаем данные из файла во второй дата-фрейм.
  • Объединяем данные (merge — по аналогии с outer join в SQL) из двух полученных дата-фреймов в один новый дата-фрейм по уникальному идентификатору и выгружаем данные из него в Excel-файл, в котором уже будем сравнивать данные по столбцам с помощью функций самого Excel.
  • Либо данные по столбцам в общем дата-фрейме можно сравнить с помощью pandas, выгружая при этом строки с одинаковыми/разными данными в столбцах в новый дата-фрейм/Excel-файл для анализа.

Пример данных из файла example3_csv.csv:

Пример данных из файла example3_json.json:

[     {         "id": "16421118-4116",         "name_json": "Tempor Consulting",         "email_json": "Nullam.lobortis.quam@estNunc.net",         "tel_json": "1-821-805-8791",         "reg_date_json": "12-11-16",         "city_json": "Natales"     },     {         "id": "16040210-2206",         "name_json": "Odio Etiam Incorporated",         "email_json": "arcu@imperdietullamcorper.edu",         "tel_json": "1-730-291-6084",         "reg_date_json": "26-06-05",         "city_json": "Viddalba"     }, ... ] 

Скрипт на python выглядит следующим образом:

# Подключаем библиотеку pandas import pandas as pd  # Загружаем данные из csv-файла в дата-фрейм # (предварительно копируем файл с данными в папку со скриптом) # При экспорте данных из БД в csv-файл лучше всего использовать разделитель ";" df_from_csv = pd.read_csv('./example3_csv.csv', sep=';', encoding='utf-8') print(df_from_csv)  # Загружаем данные из json-файла в дата-фрейм # (предварительно копируем файл с данными в папку со скриптом) df_from_json = pd.read_json('./example3_json.json', encoding='utf-8') print(df_from_json)  # Объединяем дата-фреймы в один новый дата-фрейм # (по аналогии с outer join в SQL) df_csv_json = df_from_csv.merge(df_from_json, left_on='id',                                  right_on="id", how='outer') print(df_csv_json)  # Выгружаем данные в Excel-файл, если нужно посмотреть, # что все объекты из одного файла-исходника есть во втором, # при этом указываем название для нового файла и название листа # (файл будет создан в папке со скриптом) # writer = pd.ExcelWriter('Итог.xlsx') # df_csv_json.to_excel(writer, 'Лист1') # writer.save()  # Либо сравниваем данные по двум соответствующим столбцам # (например, name_csv и name_json) и # выгружаем строки с отличающимися данными в Excel-файл для анализа # (при этом выбираем также нужные столбцы для этих строк) unequal_data_df = df_csv_json.loc[df_csv_json['name_csv'] !=                                    df_csv_json['name_json']] unequal_data_df = unequal_data_df[['id', 'name_csv', 'name_json']] print(unequal_data_df)  writer = pd.ExcelWriter('Разные_name.xlsx') unequal_data_df.to_excel(writer, 'Лист1') writer.save()  

Ограничения:

  • При работе с файлами с очень большим количеством строк придется разбивать их на отдельные файлы (тут нужно пробовать, у меня редко бывают файлы более 30 000 строк).
  • Если в json-файле есть несколько уровней вложенности объектов/массивов данных – то из внутренних уровней они будут загружены в ячейку как объект/массив, поэтому работать без какой-либо подготовки с json-файлами с помощью pandas удобно только для данных без лишней вложенности объектов/массивов.
  • Часто данные в ответе на запрос к API приходят обработанными по сравнению с данными из результата SQL-запроса в БД, поэтому для сравнения таких данных между файлами нужно будет приводить данные из SQL-запроса к нужному виду.

Если ответ на запрос к API приходит в xml формате, то нужно будет сначала распарсить нужные данные из xml-файла с помощью ElementTree или другой библиотеки и затем уже загружать их в дата-фрейм.

Сценарий №4

На UI выгружается xml-файл с данными по объектам, который формируется на лету из данных в БД с учетом определенных условий (например, учитываются статусы, даты, года или другие значения параметров для объектов).

Задача тестировщика: Сравнить уникальные идентификаторы id объектов из xml-файла, которые находятся в атрибуте тега company, с идентификаторами объектов из результата SQL-запроса в БД.

Составляем сценарий для скрипта:

  • Сохраняем данные из ответа на запрос к API в xml-файл, получаем из этого файла нужные данные с помощью библиотеки ElementTree, загружаем данные в первый дата-фрейм.
  • Выполняем SQL-запрос в БД, экспортируем данные из результата запроса в csv-файл, загрузжаем эти данные во второй дата-фрейм.
  • Объединяем данные (merge — по аналогии с outer join в SQL) из двух полученных дата-фреймов в один новый дата-фрейм по уникальному идентификатору и выгружаем данные из него в Excel-файл.
  • Дальше уже открываем полученный файл и анализируем строки с данными.

Пример данных из файла example4_csv.csv:

Пример данных из файла example4_xml.xml:

Скрипт на python выглядит следующим образом:

# Подключаем библиотеку ElementTree from xml.etree import ElementTree # Подключаем библиотеку pandas import pandas as pd  # Загружаем данные из xml-файла в объект парсера # (предварительно копируем файл с данными в папку со скриптом) tree = ElementTree.parse("example4_xml.xml")  # Получаем корневой элемент root = tree.getroot()  # Создаем список, в который будут добавляться данные data_list = [] i = 1  # Выбираем нужные данные - значения атрибута id_type1 или id_type2 for child in root.iter("companies"):     for child_1 in child.iter("company"):             data_list.append({"Номер": i, "id": child_1.get("id_type1")                                                 or child_1.get("id_type2"),                                "Из выгрузки xml": "Да"})             i += 1  # Загружаем данные из списка data_list в дата-фрейм df_from_xml = pd.DataFrame.from_dict(data_list, orient='columns') print(df_from_xml)  # Загружаем данные из csv-файла в дата-фрейм df_from_csv = pd.read_csv('./example4_csv.csv', sep=';', encoding='utf-8') print(df_from_csv)  # Объединяем дата-фреймы в один дата-фрейм # (по аналогии с outer join в SQL) df = df_from_csv.merge(df_from_xml, left_on='id', right_on="id", how='outer') print(df)  # Выгружаем данные в Excel-файл # при этом указываем название для нового файла и название листа # (файл будет создан в папке со скриптом) writer = pd.ExcelWriter('Итог.xlsx') df.to_excel(writer, 'Лист1') writer.save() 

Сценарий №5

На UI в разделе выводятся данные по объектам в виде таблицы. Есть возможность выгрузки данных в Excel-файл.

Задача тестировщика: Cравнить данные из таблицы раздела с данными, которые выгружаются в Excel-файл.

Составляем сценарий для скрипта:

  • Просим у разработчиков SQL-запрос в БД из кода, который отвечает за вывод данных в таблицу раздела на UI.
  • Выполняем этот SQL-запрос в БД, выгружаем данные в csv-файл, загружаем данные из него в первый дата-фрейм.
  • Выгружаем на UI данные из таблицы раздела в Excel-файл и загружаем данные из него во второй дата-фрейм.
  • Объединяем данные (merge — по аналогии с outer join в SQL) из двух полученных дата-фреймов в один новый дата-фрейм по уникальному идентификатору и выгрузжаем данные из него в Excel-файл, в котором уже будем сравнивать данные по столбцам с помощью функций самого Excel.
  • Либо данные по столбцам в общем дата-фрейме можно сравнить с помощью pandas, выгружая при этом строки с одинаковыми/разными данными в столбцах в новый дата-фрейм/Excel-файл для анализа.

Ограничения:

  • Часто количество строк с объектами, которые можно выгрузить в Excel-файл на UI, ограничивают, поэтому такой скрипт подойдет только для проверки тех разделов, где в файл выгрузки выгружаются все объекты из таблицы раздела.

Также аналогичные скрипты можно использовать и просто для того, чтобы данные из json-файлов или csv-файлов переносить в Excel-файлы. Либо можно объединять данные из нескольких Excel-файлов по определенным столбцам и выгружать их в один новый Excel-файл.

Заключение


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

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

ссылка на оригинал статьи https://habr.com/ru/post/486756/


Комментарии

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *