Визуализация тестового покрытия на практике

1.

Визуализация тестового
покрытия на практике
1

2.

2
Храбров
Кирилл
[email protected]
@kirill_khrabrov

3.

3
Операционные и логистические
процессы в магазинах

4.

4
Галя,
отмена!
4

5.

5
Стабильность работы нашего продукта –
критически важная цель для команды

6.

6
План
Тестовое покрытие

7.

7
План
Тестовое покрытие
Продумываем архитектуру

8.

8
План
Тестовое покрытие
Продумываем архитектуру
«Фактический результат» (FR)
«Ожидаемый результат» (ER)
Анализ FR vs ER и его визуализация

9.

9
План
Тестовое покрытие
Продумываем архитектуру
Теперь у нас есть
какой-то план и мы
будем его
придерживаться!
«Фактический результат» (FR)
«Ожидаемый результат» (ER)
Анализ FR vs ER и его визуализация
Примеры использования

10.

Тестовое
покрытие
Плотность покрытия
тестами
требований либо исполняемого
кода
10

11.

Тестовое
покрытие
Плотность покрытия
тестами
требований либо исполняемого
кода
Можно выразить в процентном
соотношении покрытия требований к
написанным тестам
11

12.

Тестовое
покрытие
12

13.

Тестовое
покрытие
13

14.

Тестовое
покрытие
14

15.

Тестовое
Собирать информацию
покрытие
по покрытию требований
сложно
15

16.

Тестовое
Собирать информацию
покрытие
по покрытию требований
сложно
Требования все время
меняются
16

17.

Тестовое
Собирать информацию
покрытие
по покрытию требований
сложно
Требования все время
меняются
Зависит от человеческого
фактора
17

18.

Тестовое
Собирать информацию
покрытие
по покрытию требований
сложно
Требования все время
меняются
Зависит от человеческого
фактора
18
Необходимо составлять
матрицы трассировки
требований

19.

Тестовое
Собирать информацию
покрытие
19
по покрытию требований
сложно
Необходимо составлять
матрицы трассировки
требований
Требования все время
меняются
Результаты анализа
не очевидны
Зависит от человеческого
фактора

20.

Тестовое
Собирать информацию
покрытие
20
по покрытию требований
сложно
Необходимо составлять
матрицы трассировки
требований
Требования все время
меняются
Результаты анализа
не очевидны
Зависит от человеческого
фактора
Требования не атомарн
или их нет вообще

21.

Тестовое
Собирать информацию
покрытие
21
по покрытию требований
сложно
Необходимо составлять
матрицы трассировки
требований
Требования все время
меняются
Результаты анализа
не очевидны
Зависит от человеческого
фактора
Требования не атомарн
или их нет вообще

22.

Тестовое
покрытие
А покрыты ли у нас
тестами методы API,
которыми часто
пользуются?
22

23.

Продумываем архитектуру
Будет красиво!
23

24.

Продумываем архитектуру
Данные об использовании API
24

25.

Продумываем архитектуру
25
Данные об использовании API
Данные о покрытых тестами методах A

26.

Продумываем архитектуру
26
Данные об использовании API
Данные о покрытых тестами методах A
Парсинг источников данных

27.

Продумываем архитектуру
27
Данные об использовании API
Данные о покрытых тестами методах A
Парсинг источников данных
Сохранение результатов парсинга

28.

Продумываем архитектуру
28
Данные об использовании API
Данные о покрытых тестами методах A
Парсинг источников данных
Сохранение результатов парсинга
Обработка результатов парсинга

29.

Продумываем архитектуру
29
Данные об использовании API
Данные о покрытых тестами методах A
Парсинг источников данных
Сохранение результатов парсинга
Обработка результатов парсинга
Визуализация результатов обработки

30.

Продумываем архитектуру
30
Данные об использовании API
Данные о покрытых тестами методах A
Парсинг источников данных
Сохранение результатов парсинга
Обработка результатов парсинга
Визуализация результатов обработки
Вывод результатов визуализации

31.

Тестовое
https://github.com/kirillkhrabrov/coverage_analisys
покрытие
31

32.

Продумываем архитектуру
ER_Data
32

33.

«Ожидаемый результат»
ER_Data
Активность пользователя можем
собирать с помощью средств анализа
веб трафика
33

34.

«Ожидаемый результат»
ER_Data
Воспроизвести
наиболее
частые
пользовательские сценарии, понять какие
методы АПИ при этом используются и
обратить наше внимание на них
34

35.

«Ожидаемый результат»
ER_Data
Активность вызовов клиентом
API методов может собираться
в логах
35

36.

«Ожидаемый результат»
ER_Data
36

37.

{
«Ожидаемый результат»
"rawResponse": {},
"hits": {
"hits": [
{
"_source": {
"full_path": "/api/departments/",
"status_code": 200,
"event": "REQUEST_SUCCESS",
"level": "info",
"method": "GET",
"time": "2023-10-31T23:26:14.372054Z"
}
},
...
]
}
ER_Data
}
37

38.

{
«Ожидаемый результат»
"rawResponse": {},
"hits": {
"hits": [
{
"_source": {
"full_path": "/api/departments/",
"status_code": 200,
"event": "REQUEST_SUCCESS",
"level": "info",
"method": "GET",
"time": "2023-10-31T23:26:14.372054Z"
}
},
...
]
}
ER_Data
}
38

39.

{
«Ожидаемый результат»
"rawResponse": {},
"hits": {
"hits": [
{
"_source": {
"full_path": "/api/departments/",
"status_code": 200,
"event": "REQUEST_SUCCESS",
"level": "info",
"method": "GET",
"time": "2023-10-31T23:26:14.372054Z"
}
},
...
]
}
ER_Data
}
39

40.

{
«Ожидаемый результат»
"rawResponse": {},
"hits": {
"hits": [
{
"_source": {
"full_path": "/api/departments/",
"status_code": 200,
"event": "REQUEST_SUCCESS",
"level": "info",
"method": "GET",
"time": "2023-10-31T23:26:14.372054Z"
}
},
...
]
}
ER_Data
}
40

41.

Продумываем архитектуру
ER_Data
FR_Data
41

42.

«Фактический результат»
FR_Data
pytest --alluredir=$ALLURE_RESULTS
42

43.

«Ожидаемый результат»
FR_Data
43

44.

«Ожидаемый результат»
FR_Data
UUID4_log_fact_result.json
UUID4_attachment.txt
UUID4_step_fact_result.json
44

45.

«Ожидаемый результат»
UUID4_log_fact_result.json
FR_Data
{
"name": "Test case ID 0e1f67c5",
"status": "passed",
"steps": [
{
"name": "Call API method POST /api/basket-local-inventory/items/",
"status": "passed"
},
...
],
"attachments": [
{
"name": "log",
"source": "2426f438-688d-4c9c-945a-0c3b97650a8a_attachment.txt",
"type": "text/plain"
}
],
"uuid": "22842bc8-4947-44c3-8025-4fd4b3dbfc1f"
}
45

46.

«Ожидаемый результат»
UUID4_log_fact_result.json
FR_Data
{
"name": "Test case ID 0e1f67c5",
"status": "passed",
"steps": [
{
"name": "Call API method POST /api/basket-local-inventory/items/",
"status": "passed"
},
...
],
"attachments": [
{
"name": "log",
"source": "2426f438-688d-4c9c-945a-0c3b97650a8a_attachment.txt",
"type": "text/plain"
}
],
"uuid": "22842bc8-4947-44c3-8025-4fd4b3dbfc1f"
}
46

47.

«Ожидаемый результат»
FR_Data
47
UUID4_attachment.txt
2023-10-30T23:26:14.145055Z:[INFO] PATCH /api/v1/items/a6a9d4a2-5bc2-439d-8708690baec6f138/item_stacks/ Response status code: 204
2023-10-31T23:26:15.227335Z:[INFO] GET /api-web/employees/ Response status
code: 200
2023-10-31T23:26:15.211632Z:[INFO] GET /api-web/info-messages-forrecipients/?ordering=-status Response status code: 200
2023-10-31T23:26:15.178278Z:[INFO] GET /api-web/info-messages/?ordering=title
Response status code: 200
2023-10-31T23:26:15.207456Z:[INFO] GET
/api/v4/tasks/?open_tasks=True&store_tasks=true Response status code: 200
2023-10-31T23:26:15.201468Z:[INFO] GET /api-web/info-messages/?ordering=title
Response status code: 200
2023-10-31T23:26:15.200463Z:[INFO] DELETE /api-web/info-messages/39db433d-4db8492e-946a-6f343c28a553/ Response status code: 204

48.

«Ожидаемый результат»
FR_Data
48
UUID4_attachment.txt
2023-10-30T23:26:14.145055Z:[INFO] PATCH /api/v1/items/a6a9d4a2-5bc2-439d-8708690baec6f138/item_stacks/ Response status code: 204
2023-10-31T23:26:15.227335Z:[INFO] GET /api-web/employees/ Response status
code: 200
2023-10-31T23:26:15.211632Z:[INFO] GET /api-web/info-messages-forrecipients/?ordering=-status Response status code: 200
2023-10-31T23:26:15.178278Z:[INFO] GET /api-web/info-messages/?ordering=title
Response status code: 200
2023-10-31T23:26:15.207456Z:[INFO] GET
/api/v4/tasks/?open_tasks=True&store_tasks=true Response status code: 200
2023-10-31T23:26:15.201468Z:[INFO] GET /api-web/info-messages/?ordering=title
Response status code: 200
2023-10-31T23:26:15.200463Z:[INFO] DELETE /api-web/info-messages/39db433d-4db8492e-946a-6f343c28a553/ Response status code: 204

49.

«Ожидаемый результат»
FR_Data
UUID4_step_fact_result.json
{
"name": "Test case ID f43581bb",
"status": "passed",
"steps": [
{
"name": "Call API method GET /api/tasks/",
"status": "passed",
"steps": [
{
"name": "Check status code 200",
"status": "passed"
}
]
},
...
],
"uuid": "f5735865-a702-46e1-973b-e84662d9806f"
}
49

50.

«Ожидаемый результат»
FR_Data
UUID4_step_fact_result.json
{
"name": "Test case ID f43581bb",
"status": "passed",
"steps": [
{
"name": "Call API method GET /api/tasks/",
"status": "passed",
"steps": [
{
"name": "Check status code 200",
"status": "passed"
}
]
},
...
],
"uuid": "f5735865-a702-46e1-973b-e84662d9806f"
}
50

51.

Продумываем архитектуру
ER_Data
DataParser
FR_Data
51

52.

DataParser
DataParser
Методы чтения источников
Методы обработки данных в
источниках
Методы сохранения информации об
API методах
52

53.

DataParser
DataParser
class DataParser:
def __init__(...):
pass
def _get_elk_response(..) -> dict:
pass
def __get_files_from_dir(...):
pass
def __read_file(...) -> str or dict:
pass
def __form_attachments_files_list_from_file(...) -> list:
pass
...
53

54.

DataParser
DataParser
54

55.

DataParser
DataParser
55

56.

DataParser
DataParser
56

57.

57
PATTERN_HTTP_REQ = r'(GET|POST|PUT|DELETE|PATCH).*(\/api\S*)'
re.findall(PATTERN_HTTP_REQ, file_content)

58.

58
http_path = '/api-web/stores/c0ff8864-e29f-41b1-867d-a741b76be6ce/'

59.

59
PATTERN_UUID4 = r'[0-9a-f]{8}-[0-9a-f]{4}-[0-5][0-9a-f]{3}-[089ab][0-9a-f]{3}-[0-9a-f]{12}'
http_after_masked_uuid = re.sub(
DataParser.PATTERN_UUID4,
'{id}',
http_path
)

60.

60
http_after_masked_uuid = '/api-web/group-tasks/{id}/'

61.

61
http_path = '/api-web/stores/B15444/dashboards/'

62.

62
PATTERN_OBJ_ID = r'\/[^v]?\d{1,5}\D?\/'
http_after_masked_id = re.sub(
DataParser.PATTERN_OBJ_ID,
'{obj_id}',
http_path
)

63.

63
http_after_masked_id = '/api-web/stores/{obj_id}/dashboards/'

64.

64
GET /api-web/stores/B15444/dashboards/c0ff8864-e29f-41b1-867da741b76be6ce/?created_from=21-09-2023&created_to=22-09-2023

65.

65
GET /api-web/stores/B15444/dashboards/{id}/?created_from=21-092023&created_to=22-09-2023

66.

66
GET /api-web/stores/{obj_id}/dashboards/{id}/?created_from=21-092023&created_to=22-09-2023

67.

67
GET /api-web/stores/{obj_id}/dashboards/{id}/?created_from=21-092023&created_to=22-09-2023
http_method = 'GET'
http_path = '/api-web/stores/{obj_id}/dashboards/{id}/'
query_params = [
'created_from=21-09-2023',
'created_to=22-09-2023'
]

68.

Продумываем архитектуру
ER_Data
DataFrame
DataFrame
DataFrame
DataParser
DataFrame
DataFrame
FR_Data
DataFrame
68

69.

69
DataFrame
DataFrame
API метод
Перечень query параметров
Статус test run
Response status codes
Критичность
Частота вызовов

70.

70
DataFrame
DataFrame
class DataFrame:
def __init__(self, api_method: str, test_status=None,
query_list=[], status_code=[]):
"""
Class for collecting info about single API Method
"""
self.api_method = api_method
self.query_list = query_list
self.passed = 1 if test_status == "passed" else 0
self.failed = 1 if test_status == "failed" else 0
self.broken = 1 if test_status == "broken" else 0
self.skipped = 1 if test_status == "skipped" else 0
self.status_codes = status_code
self.criticality = 0
self.frequency = 1

71.

71
DataFrame
DataFrame

72.

Продумываем архитектуру
ER_Data
DataFrame
DataFrame
DataSet
DataFrame
DataParser
DataFrame
DataFrame
FR_Data
DataFrame
DataSet
72

73.

73
DataSet
DataSet
Массив DataFrame’ов
Таблица критичности
Методы сохранения DataFrame’ов

74.

74
DataSet
DataSet
class DataSet:
def __init__(...):
pass
def _increase_status(self, data_frame: DataFrame):
pass
def _increase_frequency(self, data_frame: DataFrame):
pass
def _append_query_params(self, data_frame: DataFrame):
pass
def append_data_frame(self, data_frame: DataFrame):
pass

75.

75
DataSet
DataSet
def append_data_frame(self, data_frame: DataFrame):
if data_frame.api_method not in [
data_frame.api_method for data_frame in self.result_data_set
]:
self.result_data_set.append(data_frame)
self._increase_frequency(data_frame=data_frame)
self._increase_status(data_frame=data_frame)
self._append_query_params(data_frame=data_frame)
self._append_status_codes(data_frame=data_frame)
self._set_criticality(data_frame=data_frame)

76.

76
DataSet
DataSet
def _increase_frequency(self, data_frame: DataFrame):
for saved_data_frame in self.result_data_set:
if saved_data_frame.api_method == data_frame.api_method:
saved_data_frame.frequency += 1
self.logger.debug(f"increased frequency for
{saved_data_frame.api_method}")

77.

Продумываем архитектуру
DataSet
77

78.

Продумываем архитектуру
ER_Data
DataFrame
DataFrame
DataSet
DataFrame
Coverage
Analysis
DataParser
DataFrame
DataFrame
FR_Data
DataFrame
DataSet
78

79.

79
CoverageAnalysis
Coverage
Analysis
Методы обработки DataSet’ов
Методы получения
результирующих массивов
данных

80.

80
ER
CoverageAnalysis
Непротестированные
используемые API методы
FR
Протестированные
неиспользуемые API
методы
Протестированные
используемые API
методы

81.

81
CoverageAnalysis
Coverage
Analysis
class CoverageAnalisys:
def __init__(...):
pass
def get_untested_status_codes_params(...) -> list:
pass
def get_untested_query_params(...) -> list:
pass
def get_untested_used_api_methods(...) -> list:
pass
def get_tested_api_methods(...) -> list:
pass
def get_fact_stat(...) -> list:
pass

82.

82
CoverageAnalysis
Coverage
Analysis
def get_untested_used_api_methods(
self,
expected_result_lst: list = None,
fact_result_lst: list = None
) -> list:
expected_list = expected_result_lst if expected_result_lst else
self.expected_data_set_result
fact_list = fact_result_lst if fact_result_lst else
self.fact_data_set_result
return list(filter(
lambda data_frame: data_frame.api_method not in [
data_frame.api_method for data_frame in fact_list
],
expected_list
))

83.

83
CoverageAnalysis
Coverage
Analysis
top_50_expected_sorted_by_freq =
coverage_analyzer.get_top_n_api_methods(
data_set=expected_data_set,
top_n=50
)
untested_from_top_50_api_methods_freq =
coverage_analyzer.get_untested_used_api_methods(
expected_result_lst=top_50_expected_sorted_by_freq
)

84.

84
CoverageAnalysis
Coverage
Analysis

85.

Продумываем архитектуру
ER_Data
DataFrame
DataFrame
DataSet
DataFrame
Coverage
Analysis
DataParser
DataFrame
DataFrame
FR_Data
DataFrame
DataSet
Coverage
Visualize
85

86.

86
CoverageVisualize
Coverage
Visualize
Pandas
Python библиотека для
анализа данных

87.

87
CoverageVisualize
Coverage
Visualize
Pandas
Python библиотека для
анализа данных
Series
Data
Frame
Series
Series
Series
Одномерный
массив
c
набором
ассоциированных
меток
(индексов),
вдоль
каждого элемента из списка.
DataFrame
является
табличной
структурой
данных, столбцы, строки объекты Series

88.

88
CoverageVisualize
Coverage
Visualize
Варианты
отображения

89.

89
CoverageVisualize
Coverage
Visualize

90.

90
CoverageVisualize
Coverage
Visualize
Таблица
Круговая диаграмма
Столбчатая гистограмма

91.

91
CoverageVisualize
Coverage
Visualize
Процесс Конвертации в pandas’
DataFrame
Методы визуализации результатов
обработки DataSet’ов

92.

92
CoverageVisualize
Coverage
Visualize
class PData:
def __init__(self, data: list, columns: list, sort_by: str = None):
out_data = []
for data_frame in data:
data_part = [
getattr(data_frame, attr_name) for attr_name in columns
]
out_data.append(data_part)
self.data = out_data
self.columns = columns
self.df = pd.DataFrame(self.data, columns=self.columns)
if sort_by:
self.df.sort_values(by=sort_by)

93.

93
CoverageVisualize
Coverage
Visualize
class CoverageVisualize:
"""
Class for building tables, hists, diagrams
and saving it to pandas_results dir
"""
@staticmethod
def build_info_table(...):
pass
@staticmethod
def build_info_gist_on_code_coverage(...):
pass
@staticmethod
def build_info_barh_on_code_coverage(...):
pass

94.

94
Знаете, я и сам своего
рода визуализатор

95.

Применение
Топ 50 используемых API методов, отсортированных по
частоте
Топ 50 используемых API методов, отсортированных по
критичности
95

96.

Применение
Топ 50 используемых API методов, отсортированных по
частоте
Топ 50 используемых API методов, отсортированных по
критичности
Протестированные API методы, отсортированные по частоте
Протестированные API методы, отсортированные по
критичности
96

97.

Применение
97
Топ 50 используемых API методов, отсортированных по
частоте
Топ 50 используемых API методов, отсортированных по
критичности
Протестированные API методы, отсортированные по частоте
Протестированные API методы, отсортированные по
критичности
Не покрытые тестами query параметры из Топ 50 критичных
используемых
методовstatus codes из Топ 50 критичных используемых
Не покрытые тестами
методов

98.

Применение
98
Топ 50 используемых API методов, отсортированных по
частоте
Топ 50 используемых API методов, отсортированных по
критичности
Протестированные API методы, отсортированные по частоте
Протестированные API методы, отсортированные по
критичности
Не покрытые тестами query параметры из Топ 50 критичных
используемых
методовstatus codes из Топ 50 критичных используемых
Не покрытые тестами
методов
Не протестированные критичные API методы из ТОП 50
Не протестированные частые API методы из ТОП 50

99.

Применение
99
Топ 50 используемых API методов, отсортированных по
частоте
Топ 50 используемых API методов, отсортированных по
критичности
Протестированные API методы, отсортированные по частоте
Протестированные API методы, отсортированные по
критичности
Не покрытые тестами query параметры из Топ 50 критичных
используемых
методовstatus codes из Топ 50 критичных используемых
Не покрытые тестами
методов
Не протестированные критичные API методы из ТОП 50
Не протестированные частые API методы из ТОП 50
Структура прогона тестов самых популярных API методов
Диаграмма покрытия API тестами

100.

Применение
Топ 50 используемых API методов,
отсортированных по частоте
top_50_expected_sorted_by_freq = coverage_analyzer.get_top_n_api_methods(
data_set=expected_data_set,
top_n=50
)
top_50_expected_sorted_by_freq_df = PData(
data=top_50_expected_sorted_by_freq,
columns=["api_method", "frequency"],
sort_by='frequency'
).df
CoverageVisualize.build_info_table(
df=top_50_expected_sorted_by_freq_df,
title='Топ 50 используемых API методов, отсортированных по частоте'
)
100

101.

Применение
Топ 50 используемых API методов,
отсортированных по частоте
top_50_expected_sorted_by_freq = coverage_analyzer.get_top_n_api_methods(
data_set=expected_data_set,
top_n=50
)
top_50_expected_sorted_by_freq_df = PData(
data=top_50_expected_sorted_by_freq,
columns=["api_method", "frequency"],
sort_by='frequency'
).df
CoverageVisualize.build_info_table(
df=top_50_expected_sorted_by_freq_df,
title='Топ 50 используемых API методов, отсортированных по частоте'
)
101

102.

Применение
Топ 50 используемых API методов,
отсортированных по частоте
top_50_expected_sorted_by_freq = coverage_analyzer.get_top_n_api_methods(
data_set=expected_data_set,
top_n=50
)
top_50_expected_sorted_by_freq_df = PData(
data=top_50_expected_sorted_by_freq,
columns=["api_method", "frequency"],
sort_by='frequency'
).df
CoverageVisualize.build_info_table(
df=top_50_expected_sorted_by_freq_df,
title='Топ 50 используемых API методов, отсортированных по частоте'
)
102

103.

Применение
103
Топ 50 используемых API методов,
отсортированных по частоте
api_method
frequency
GET /api-web/info-messages/
577
GET /api/v2/basket-local-inventory/
557
GET /api/v2/basket/
403
GET /api/seals/actions/{id}/
392
DELETE /api-web/info-messages/{id}/
336
GET /api-web/info-messages-for-recipients/
301
GET /api/items/{id}/
292
PATCH /api/v1/items/{id}/item_stacks/
291
GET /api-web/group-poll-tasks/{id}/
286
GET /api-web/group-poll-tasks/{id}/tasks/
284
GET /api-web/group-tasks/{id}/
284

104.

Применение
Топ 50 используемых API методов,
отсортированных по критичности
top_50_expected_sorted_by_crit = coverage_analyzer.get_top_n_api_methods(
data_set=expected_data_set,
top_n=50,
sort_by='criticality'
)
top_50_expected_sorted_by_crit_df = PData(
data=top_50_expected_sorted_by_crit,
columns=["api_method", "criticality"],
sort_by='criticality'
).df
CoverageVisualize.build_info_table(
df=top_50_expected_sorted_by_crit_df,
title='Топ 50 используемых API методов, отсортированных по критичности'
)
104

105.

Применение
105
Топ 50 используемых API методов,
отсортированных по критичности
api_method
criticality
GET /api/config/
1.0
PATCH /api/config/
1.0
GET /api/v5/main/
1.0
POST /api/v1/login/
1.0
PATCH /api/employees/{obj_id}/
0.9
GET /api/employees/{obj_id}/
0.9
GET /api/employees/
0.9
PATCH /api/tasks/{id}/state/
0.8
GET /api/tasks/{id}/
0.8
GET /api/v4/tasks/{id}/
0.8
POST /api/tasks/{id}/submit-poll-task-answers/
0.8

106.

Применение
Не покрытые тестами query
параметры из Топ 50 критичных
используемых методов
untested_queries_from_top_50_expected =
coverage_analyzer.get_untested_query_params(
expected_result_lst=top_50_expected_sorted_by_crit,
fact_result_lst=fact_sorted_by_crit
)
untested_queries_from_top_50_expected_df = PData(
data=untested_queries_from_top_50_expected,
columns=["api_method", "query_list", "criticality"],
sort_by='criticality'
).df
CoverageVisualize.build_info_table(
df=untested_queries_from_top_50_expected_df,
title='Не покрытые тестами query параметры из Топ 50 критичных
используемых методов'
)
106

107.

Применение
Не покрытые тестами query
параметры из Топ 50 критичных
используемых методов
untested_queries_from_top_50_expected =
coverage_analyzer.get_untested_query_params(
expected_result_lst=top_50_expected_sorted_by_crit,
fact_result_lst=fact_sorted_by_crit
)
untested_queries_from_top_50_expected_df = PData(
data=untested_queries_from_top_50_expected,
columns=["api_method", "query_list", "criticality"],
sort_by='criticality'
).df
CoverageVisualize.build_info_table(
df=untested_queries_from_top_50_expected_df,
title='Не покрытые тестами query параметры из Топ 50 критичных
используемых методов'
)
107

108.

Применение
Не покрытые тестами query
параметры из Топ 50 критичных
используемых методов
untested_queries_from_top_50_expected =
coverage_analyzer.get_untested_query_params(
expected_result_lst=top_50_expected_sorted_by_crit,
fact_result_lst=fact_sorted_by_crit
)
untested_queries_from_top_50_expected_df = PData(
data=untested_queries_from_top_50_expected,
columns=["api_method", "query_list", "criticality"],
sort_by='criticality'
).df
CoverageVisualize.build_info_table(
df=untested_queries_from_top_50_expected_df,
title='Не покрытые тестами query параметры из Топ 50 критичных
используемых методов'
)
108

109.

Применение
Не покрытые тестами query
параметры из Топ 50 критичных
используемых методов
untested_queries_from_top_50_expected =
coverage_analyzer.get_untested_query_params(
expected_result_lst=top_50_expected_sorted_by_crit,
fact_result_lst=fact_sorted_by_crit
)
untested_queries_from_top_50_expected_df = PData(
data=untested_queries_from_top_50_expected,
columns=["api_method", "query_list", "criticality"],
sort_by='criticality'
).df
CoverageVisualize.build_info_table(
df=untested_queries_from_top_50_expected_df,
title='Не покрытые тестами query параметры из Топ 50 критичных
используемых методов'
)
109

110.

Применение
110
Не покрытые тестами query
параметры из Топ 50 критичных
используемых методов
api_method
query_list
criticality
GET /api-web/info-messages/
['ordering=-total_recipients_number',
'search=name’, 'ordering=title',
'ordering=total_recipients_number',
'ordering=created_at', 'ordering=-title']
0.5
GET /api/items/
['plu=3215907', 'plu=1048', 'plu=5680',
'plu=2046261', 'plu=4059501']
0.0

111.

Применение
Не покрытые тестами status codes
из
Топ
50
критичных
используемых методов
untested_codes_from_top_50_expected =
coverage_analyzer.get_untested_status_codes_params(
expected_result_lst=top_50_expected_sorted_by_crit,
fact_result_lst=fact_sorted_by_crit
)
untested_codes_from_top_50_expected_df = PData(
data=untested_codes_from_top_50_expected,
columns=["api_method", "status_codes", "criticality"],
sort_by='criticality'
).df
CoverageVisualize.build_info_table(
df=untested_codes_from_top_50_expected_df,
title='Не покрытые тестами status codes из Топ 50 критичных
используемых методов'
)
111

112.

Применение
Не покрытые тестами status codes
из
Топ
50
критичных
используемых методов
untested_codes_from_top_50_expected =
coverage_analyzer.get_untested_status_codes_params(
expected_result_lst=top_50_expected_sorted_by_crit,
fact_result_lst=fact_sorted_by_crit
)
untested_codes_from_top_50_expected_df = PData(
data=untested_codes_from_top_50_expected,
columns=["api_method", "status_codes", "criticality"],
sort_by='criticality'
).df
CoverageVisualize.build_info_table(
df=untested_codes_from_top_50_expected_df,
title='Не покрытые тестами status codes из Топ 50 критичных
используемых методов'
)
112

113.

Применение
Не покрытые тестами status codes из
Топ 50 критичных используемых
методов
api_method
113
status_codes
criticality
GET /api/stores/{obj_id}/markdown-items/
[503]
0.9
GET /api/employees/{obj_id}/
[500]
0.9
PATCH /api/employees/{obj_id}/
[404]
0.9
[400, 401]
0.9
[400, 401, 404]
0.8
GET /api/v4/tasks/{id}/
[500, 503]
0.8
GET /api/tasks/{id}/
[500]
0.8
[400, 404]
0.8
DELETE /api/basket-placing/{id}/
[500]
0.7
PATCH /api/basket-placing/
[401]
0.7
POST /api/v2/basket/items/
[400]
0.7
DELETE /api/stores/{obj_id}/markdown-items/{id}/
PATCH /api/tasks/{id}/state/
POST /api/tasks/{id}/submit-poll-task-answers/

114.

Применение
Не
протестированные
критичные API методы из ТОП
50
untested_from_top_50_api_methods_crit =
coverage_analyzer.get_untested_used_api_methods(
expected_result_lst=top_50_expected_sorted_by_crit
)
untested_from_top_50_api_methods_crit_df = PData(
data=untested_from_top_50_api_methods_crit,
columns=["api_method", "criticality"],
sort_by='criticality'
).df
CoverageVisualize.build_info_table(
df=untested_from_top_50_api_methods_crit_df,
title='Не протестированные критичные API методы из ТОП 50'
)
114

115.

Применение
Не
протестированные
критичные API методы из ТОП
50
api_method
115
criticality
GET /api/employees/delegate/
0.9
GET /api/stores/{obj_id}/markdown-filters/
0.9
PATCH /api/employees/set_default_clear/
0.9
POST /api/stores/{obj_id}/markdown-items/{id}/markdown_created/
0.9
GET /api/v5/tasks/
0.8
PATCH /api/tasks/{id}/items/
0.8
GET /api/basket-placing/
0.7
POST /api/basket-placing/
0.7
POST /api/basket-local-inventory/update_and_get_all_items/
0.7
GET /api-web/statistics/
0.5

116.

Применение
Структура прогона тестов
самых
популярных
API
методов
top_15_fact_stat = coverage_analyzer.get_fact_stat(
expected_result_lst=coverage_analyzer.get_top_n_api_methods(fact_data_set, 15)
)
stats_for_tested_from_top_df = PData(
data=coverage_analyzer.get_fact_stat(top_15_fact_stat),
columns=["api_method", "skipped", "broken", "passed", "failed", "frequency"],
sort_by='frequency'
).df
barh_stats_for_tested_from_top = CoverageVisualize.build_info_barh_on_code_coverage(
df=stats_for_tested_from_top_df,
title='Структура прогона тестов самых популярных API методов',
xlabel='Количество вызовов в тестах',
ylabel="Методы API",
x="api_method",
y=["broken", "skipped", "passed", "failed"])
116

117.

Применение
Структура прогона тестов
самых
популярных
API
методов
117

118.

Применение
Диаграмма
тестами
покрытия
API
all_untested = coverage_analyzer.get_untested_used_api_methods()
all_tested = coverage_analyzer.get_tested_api_methods()
gist = CoverageVisualize.build_info_gist_on_code_coverage(
values=[len(all_tested), len(all_untested)],
labels=["Покрыто", "Не Покрыто"],
title='Диаграмма покрытия API тестами'
)
118

119.

Применение
Диаграмма
тестами
покрытия
API
all_untested = coverage_analyzer.get_untested_used_api_methods()
all_tested = coverage_analyzer.get_tested_api_methods()
gist = CoverageVisualize.build_info_gist_on_code_coverage(
values=[len(all_tested), len(all_untested)],
labels=["Покрыто", "Не Покрыто"],
title='Диаграмма покрытия API тестами'
)
119

120.

Применение
Диаграмма
тестами
покрытия
API
all_untested = coverage_analyzer.get_untested_used_api_methods()
all_tested = coverage_analyzer.get_tested_api_methods()
gist = CoverageVisualize.build_info_gist_on_code_coverage(
values=[len(all_tested), len(all_untested)],
labels=["Покрыто", "Не Покрыто"],
title='Диаграмма покрытия API тестами'
)
120

121.

Применение
Диаграмма
тестами
покрытия
API
33,3%
Не покрыто
66,7%
Покрыто
121

122.

Как выдать результат
plt.savefig(os.path.abspath('pandas_results') + f'/{kwargs["title"]}.pdf')
122

123.

Как выдать результат
stages:
- linting
- build
- run-tests
- coverage
coverage_vis:
stage: coverage
script:
- ls
- mkdir pandas_results
- python coverage_visualizer.py
artifacts:
paths:
- ./pandas_results/*
rules:
- if: $CI_PIPELINE_SOURCE == "merge_request_event" ||
$CI_PIPELINE_SOURCE == "push"
when: manual
- when: always
123

124.

Как выдать результат
stages:
- linting
- build
- run-tests
- coverage
coverage_vis:
stage: coverage
script:
- ls
- mkdir pandas_results
- python coverage_visualizer.py
artifacts:
paths:
- ./pandas_results/*
rules:
- if: $CI_PIPELINE_SOURCE == "merge_request_event" ||
$CI_PIPELINE_SOURCE == "push"
when: manual
- when: always
124

125.

Как выдать результат
stages:
- linting
- build
- run-tests
- coverage
coverage_vis:
stage: coverage
script:
- ls
- mkdir pandas_results
- python coverage_visualizer.py
artifacts:
paths:
- ./pandas_results/*
rules:
- if: $CI_PIPELINE_SOURCE == "merge_request_event" ||
$CI_PIPELINE_SOURCE == "push"
when: manual
- when: always
125

126.

Как выдать результат
stages:
- linting
- build
- run-tests
- coverage
coverage_vis:
stage: coverage
script:
- ls
- mkdir pandas_results
- python coverage_visualizer.py
artifacts:
paths:
- ./pandas_results/*
rules:
- if: $CI_PIPELINE_SOURCE == "merge_request_event" ||
$CI_PIPELINE_SOURCE == "push"
when: manual
- when: always
126

127.

Как выдать результат
stages:
- linting
- build
- run-tests
- coverage
coverage_vis:
stage: coverage
script:
- ls
- mkdir pandas_results
- python coverage_visualizer.py
artifacts:
paths:
- ./pandas_results/*
rules:
- if: $CI_PIPELINE_SOURCE == "merge_request_event" ||
$CI_PIPELINE_SOURCE == "push"
when: manual
- when: always
127

128.

Анализ ER vs FR и его визуализация
128

129.

Итоги
Пришло время
подводить итоги
129

130.

Итоги
Получить информацию о пользовательской
активности использования API
130

131.

Итоги
Получить информацию о пользовательской
активности использования API
Быстро получить информацию о
соотношении покрытых / не покрытых авто
тестами API методах
131

132.

Итоги
Получить информацию о пользовательской
активности использования API
Быстро получить информацию о
соотношении покрытых / не покрытых авто
тестами API методах
Сконцентрироваться на покрытии реально
используемых API методах
132

133.

Итоги
Получить информацию о пользовательской
активности использования API
Быстро получить информацию о
соотношении покрытых / не покрытых авто
тестами API методах
Сконцентрироваться на покрытии реально
используемых API методах
Сократить количество не покрытых тестами API
методов
133
English     Русский Правила