Skip to content

Commit 2ad6fbd

Browse files
committed
Big refactoring. Fixed several bugs. Removed sensitive data
1 parent 434cc60 commit 2ad6fbd

3 files changed

Lines changed: 85 additions & 24 deletions

File tree

main.py

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,8 @@
33
Пример программы:
44
55
if __name__ == '__main__':
6-
stress = StressTest('https://coursemc.space')
7-
stress.timeout = 0.1
6+
stress = StressTest('http://127.0.0.1:8000')
7+
stress.timeout = 0.5
88
stress.max_execution_time = 60
99
stress.max_thread_count = 100
1010
monitor = ChartMonitor(stress)
@@ -16,9 +16,9 @@
1616
from stress_test import StressTest
1717
from monitor import ChartMonitor
1818

19-
stress = StressTest('https://coursemc.space')
20-
stress.timeout = 0.1
21-
stress.max_execution_time = 60
19+
stress = StressTest('http://127.0.0.1:8000')
20+
stress.timeout = 0.5
21+
stress.max_execution_time = 10
2222
stress.max_thread_count = 100
2323
monitor = ChartMonitor(stress)
2424
monitor.start()

monitor.py

Lines changed: 68 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import time
2+
from statistics import mean
23
from typing import Optional, Union, Tuple
34

45
from matplotlib import pyplot as plt
@@ -11,25 +12,49 @@ class BaseMonitor(AbstractMonitor):
1112
def __init__(self, stress: AbstractStressTest):
1213
self._stress = stress
1314

14-
def start(self, timeout: Union[int, float] = 0.2):
15+
def start(self, timeout: Union[int, float] = 0.2) -> None:
16+
"""
17+
Запускает тест.
18+
:param timeout: Union[int, float] (время задержки, используется при создании потоков и отправки запросов)
19+
:return: None
20+
"""
1521
self._stress.auto_create_connection()
1622
for _ in self._stress.auto_get_stats(timeout):
17-
print(f'Запросов всего: {len(self._stress.stats)}')
23+
print(f'Всего запросов: {len(self._stress.stats)}')
1824

1925
def set_params(self, kill: Optional[bool] = None, timeout: Optional[Union[float, int]] = None,
20-
max_thread_count: Optional[int] = None, max_execution_time: Optional[int] = None):
26+
max_thread_count: Optional[int] = None, max_execution_time: Optional[int] = None) -> None:
27+
"""
28+
Устанавливает параметры стресс-теста.
29+
:param kill: bool (True - убить потоки, False - продолжить тестирование)
30+
:param timeout: Union[int, float] (время задержки, используется при создании потоков и отправки запросов)
31+
:param max_thread_count: int (максимальное кол-во потоков,
32+
реальное кол-во может незначительно отличаться от заданного)
33+
:param max_execution_time: int (максимальное время выполнения теста)
34+
:return: None
35+
"""
2136
self._stress.kill = kill or self._stress.kill
2237
self._stress.timeout = timeout or self._stress.timeout
2338
self._stress.max_thread_count = max_thread_count or self._stress.max_thread_count
2439
self._stress.max_execution_time = max_execution_time or self._stress.max_execution_time
2540

26-
def stop(self):
41+
def stop(self) -> None:
42+
"""
43+
Останавливает работу теста и запускает построение статистики.
44+
:return: None
45+
"""
2746
self._stress.kill_all_connections()
2847
self.build_graph()
2948

3049

3150
class ChartMonitor(BaseMonitor):
32-
def build_graph(self):
51+
def build_graph(self) -> None:
52+
"""
53+
Построить статистику в виде графика. Используется matplotlib.
54+
Первый график - зависимость времени выполнения запроса от кол-ва запросов.
55+
Второй график - зависимость кол-ва ошибок от кол-ва запросов.
56+
:return: None
57+
"""
3358
stats = sorted(self._stress.stats.items(), key=lambda i: i[0])
3459
x_time_request = list(map(lambda i: round(time.time() - i[0], 4), stats))
3560
y_time_request = list(map(lambda i: round(i[1], 4), stats))
@@ -42,6 +67,14 @@ def build_graph(self):
4267
plt.show()
4368

4469
def _get_x_y_error_coord(self) -> Tuple[list, list]:
70+
"""
71+
Получение кортежа с координатами ошибок x, y.
72+
tuple[0] - list (координата x)
73+
tuple[1] - list (координата y)
74+
В качестве координат x, идёт время, когда проищошла ошибка.
75+
В качестве координат y, идёт кол-во ошибок, которое проищошло за время указанное в x (по умолчанию за 1 секунду)
76+
:return: Tuple[list, list]
77+
"""
4578
res = [[]]
4679
x_error = y_error = []
4780
if len(self._stress.errors) > 0:
@@ -57,12 +90,22 @@ def _get_x_y_error_coord(self) -> Tuple[list, list]:
5790
res.append([i])
5891
back = i[0]
5992
# Получаем время когда проихошла ошибка
60-
x_error = list(map(lambda i: round(time.time() - i, 4), [i[0][0] for i in res]))
93+
x_error = list(map(lambda el: round(time.time() - el, 4), [i[0][0] for i in res]))
6194
# Получаем кол-во ошибок
6295
y_error = [len(i) for i in res]
6396
return x_error, y_error
6497

65-
def _draw_plot(self, x: list, y: list, coord: Optional[list] = None, title: Optional[str] = None, color: str = 'b'):
98+
def _draw_plot(self, x: list, y: list, coord: Optional[list] = None, title: Optional[str] = None,
99+
color: str = 'b') -> None:
100+
"""
101+
Строит график по указанным координатам x, y.
102+
:param x: list (координаты x (работает при условии len(x) == len(y)))
103+
:param y: list (координаты y (работает при условии len(x) == len(y)))
104+
:param coord: Optional[list] (координаты разбивания графика (matplotlib.subplot))
105+
:param title: Optional[str] (название графика (matplotlib.title))
106+
:param color: str (цвет графика)
107+
:return: None
108+
"""
66109
if coord:
67110
plt.subplot(*coord)
68111
plt.plot(x, y, c=color)
@@ -72,7 +115,12 @@ def _draw_plot(self, x: list, y: list, coord: Optional[list] = None, title: Opti
72115

73116

74117
class CMDMonitor(BaseMonitor):
75-
def start(self, timeout: Union[int, float] = 0.2):
118+
def start(self, timeout: Union[int, float] = 0.2) -> None:
119+
"""
120+
Запускает тест, отобрадение статистики происходит в терминале.
121+
:param timeout: Union[int, float] (время задержки, используется при создании потоков и отправки запросов)
122+
:return: None
123+
"""
76124
self._stress.auto_create_connection()
77125
for i in self._stress.auto_get_stats(0.2):
78126
if isinstance(i, int):
@@ -82,12 +130,19 @@ def start(self, timeout: Union[int, float] = 0.2):
82130
print(f'Запросов всего: {len(self._stress.stats)}')
83131
print(f'Ошибок: {len(self._stress.errors)}', end='\n\n\n')
84132

85-
def build_graph(self):
133+
def build_graph(self) -> None:
134+
"""
135+
Строит график в терминале.
136+
Параметры вывода:
137+
1) Всего потоков
138+
2) Всего запросов
139+
3) Среднее время на запрос
140+
4) Всего ошибок
141+
:return: None
142+
"""
86143
stats = self._stress.stats.items()
87-
total_runtime = 0
88-
for i in stats:
89-
total_runtime += i[1]
144+
average_time_per_request = mean([i[1] for i in stats])
90145
print(f'\n\n\nВсего потоков: {len(self._stress.thread)}')
91146
print(f'Всего запросов: {len(stats)}')
92-
print(f'Среднее время на запрос: {len(stats) / total_runtime}')
147+
print(f'Среднее время на запрос: {average_time_per_request}')
93148
print(f'Всего ошибок: {len(self._stress.errors)}', end='\n\n\n')

stress_test.py

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,11 @@
11
import time
22
import threading
33
import warnings
4-
from pprint import pprint
54
from typing import Optional, NoReturn, Union
65

76
import requests
87

98
from abstarct.stress_test import AbstractStressTest
10-
from monitor import ChartMonitor, CMDMonitor
119

1210

1311
class StressTest(AbstractStressTest):
@@ -142,7 +140,7 @@ def _start_connection_stress_test(self, connection_type: str) -> None:
142140
self._check_response_status_code(response)
143141
time.sleep(self._timeout)
144142

145-
def _check_response_status_code(self, response):
143+
def _check_response_status_code(self, response) -> None:
146144
"""
147145
Если код ответа != 200, записывает в self._errors
148146
(см. в __init__, что записывается в self._errors).
@@ -181,7 +179,11 @@ def _get_runtime(func, *args, **kwargs) -> tuple:
181179
response = func(*args, **kwargs)
182180
return response, time.time() - time_start
183181

184-
def _get_last_number_errors(self):
182+
def _get_last_number_errors(self) -> int:
183+
"""
184+
Получить последние ошибки.
185+
:return: None
186+
"""
185187
result = len(self._errors) - self._previous_count_errors
186188
self._previous_count_errors = len(self._errors)
187189
return result
@@ -216,6 +218,11 @@ def max_execution_time(self) -> Union[int, float]:
216218

217219
@max_execution_time.setter
218220
def max_execution_time(self, value: Union[int, float]) -> None:
221+
"""
222+
Устанавливает максимальное время тестирования.
223+
:param value: Union[int, float](value >= 0)
224+
:return: None
225+
"""
219226
if not isinstance(value, (int, float)) or value <= 0:
220227
raise ValueError('Значение max_execution_time может быть только типа int, float > 0')
221228
self._max_execution_time = value
@@ -228,8 +235,7 @@ def max_thread_count(self):
228235
def max_thread_count(self, value: int):
229236
"""
230237
Устанавливает максимальное кол-во потоков.
231-
Должно быть int и > 20.
232-
:param value: int
238+
:param value: int (value > 20)
233239
:return: None
234240
"""
235241
if not isinstance(value, int) or value != abs(value) or value < 20:

0 commit comments

Comments
 (0)