Skip to content

Commit fbc69e8

Browse files
committed
options: add --runtime option
Iterate testing suites until they reach a specific runtime value, given by the --runtime option. If the given runtime is smaller than the testing suite execution time, session will gracefully stop. Reviewed-by: Petr Vorel <pvorel@suse.cz> Signed-off-by: Andrea Cervesato <andrea.cervesato@suse.com>
1 parent 79ebb45 commit fbc69e8

File tree

4 files changed

+136
-37
lines changed

4 files changed

+136
-37
lines changed

libkirk/main.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -363,6 +363,7 @@ async def session_run() -> None:
363363
suite_iterate=args.suite_iterate,
364364
skip_tests=skip_tests,
365365
randomize=args.randomize,
366+
runtime=args.runtime,
366367
)
367368
except asyncio.CancelledError:
368369
await session.stop()
@@ -501,6 +502,12 @@ def run(cmd_args: list = None) -> None:
501502
"-x",
502503
action="store_true",
503504
help="Force parallelization execution of all tests")
505+
parser.add_argument(
506+
"--runtime",
507+
"-u",
508+
type=_time_config,
509+
default="0",
510+
help="Set for how long we want to run the session in seconds")
504511

505512
# session arguments
506513
parser.add_argument(

libkirk/session.py

Lines changed: 62 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,7 @@ def __init__(self, **kwargs) -> None:
6868
self._stop = False
6969
self._exec_lock = asyncio.Lock()
7070
self._run_lock = asyncio.Lock()
71+
self._results = []
7172

7273
if not self._tmpdir:
7374
raise ValueError("tmpdir is empty")
@@ -358,6 +359,48 @@ async def stop(self) -> None:
358359
await libkirk.events.fire("session_stopped")
359360
self._stop = False
360361

362+
async def _schedule_once(self, suites_obj: list) -> None:
363+
"""
364+
Schedule tests only once.
365+
"""
366+
await self._scheduler.schedule(suites_obj)
367+
self._results.extend(self._scheduler.results)
368+
369+
async def _schedule_infinite(self, suites_obj: list) -> None:
370+
"""
371+
Schedule all testing suites infinite times.
372+
"""
373+
suites_list = []
374+
suites_list.extend(suites_obj)
375+
376+
count = 1
377+
while not self._stop:
378+
await self._schedule_once(suites_obj)
379+
if self._scheduler.stopped:
380+
break
381+
382+
count += 1
383+
384+
suites_list.clear()
385+
for suite in copy.deepcopy(suites_obj):
386+
suite.name = f"{suite.name}[{count}]"
387+
suites_list.append(suite)
388+
389+
async def _run_scheduler(self, suites_obj: list, runtime: int) -> None:
390+
"""
391+
Run the scheduler for specific amount of time given by `runtime`.
392+
"""
393+
if runtime <= 0:
394+
await self._schedule_once(suites_obj)
395+
return
396+
397+
try:
398+
await asyncio.wait_for(
399+
self._schedule_infinite(suites_obj),
400+
runtime)
401+
except asyncio.TimeoutError:
402+
await self._scheduler.stop()
403+
361404
async def run(self, **kwargs: dict) -> None:
362405
"""
363406
Run a new session and store results inside a JSON file.
@@ -377,16 +420,9 @@ async def run(self, **kwargs: dict) -> None:
377420
:type suite_iterate: int
378421
:param randomize: randomize all tests if True
379422
:type randomize: bool
423+
:param runtime: for how long we want to run the session
424+
:type runtime: int
380425
"""
381-
command = kwargs.get("command", None)
382-
suites = kwargs.get("suites", None)
383-
pattern = kwargs.get("pattern", None)
384-
skip_tests = kwargs.get("skip_tests", None)
385-
report_path = kwargs.get("report_path", None)
386-
restore = kwargs.get("restore", None)
387-
suite_iterate = kwargs.get("suite_iterate", 1)
388-
randomize = kwargs.get("randomize", False)
389-
390426
async with self._run_lock:
391427
await libkirk.events.fire("session_started", self._tmpdir.abspath)
392428

@@ -398,44 +434,53 @@ async def run(self, **kwargs: dict) -> None:
398434
try:
399435
await self._start_sut()
400436

437+
command = kwargs.get("command", None)
401438
if command:
402439
await self._exec_command(command)
403440

441+
suites = kwargs.get("suites", None)
404442
if suites:
405443
suites_obj = await self._read_suites(
406-
suites, pattern, skip_tests, restore)
444+
suites,
445+
kwargs.get("pattern", None),
446+
kwargs.get("skip_tests", None),
447+
kwargs.get("restore", False))
407448

408449
suites_obj = self._apply_iterate(
409-
suites_obj, suite_iterate)
450+
suites_obj,
451+
kwargs.get("suite_iterate", 1))
410452

411-
if randomize:
453+
if kwargs.get("randomize", False):
412454
for suite in suites_obj:
413455
random.shuffle(suite.tests)
414456

415-
await self._scheduler.schedule(suites_obj)
457+
await self._run_scheduler(
458+
suites_obj,
459+
kwargs.get("runtime", 0))
416460
except KirkException as err:
417461
if not self._stop:
418462
self._logger.exception(err)
419463
await libkirk.events.fire("session_error", str(err))
420464
raise err
421465
finally:
422466
try:
423-
if self._scheduler.results:
467+
if self._results:
424468
exporter = JSONExporter()
425469

426470
tasks = []
427471
tasks.append(
428472
exporter.save_file(
429-
self._scheduler.results,
473+
self._results,
430474
os.path.join(
431475
self._tmpdir.abspath,
432476
"results.json")
433477
))
434478

479+
report_path = kwargs.get("report_path", None)
435480
if report_path:
436481
tasks.append(
437482
exporter.save_file(
438-
self._scheduler.results,
483+
self._results,
439484
report_path
440485
))
441486

@@ -449,4 +494,5 @@ async def run(self, **kwargs: dict) -> None:
449494
await libkirk.events.fire("session_error", str(err))
450495
raise err
451496
finally:
497+
self._results.clear()
452498
await self._inner_stop()

libkirk/tests/test_main.py

Lines changed: 53 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@
44
import os
55
import sys
66
import pwd
7-
import time
87
import json
98
import pytest
109
import libkirk.main
@@ -22,7 +21,7 @@ def setup(self, dummy_framework):
2221
"""
2322
libkirk.main.LOADED_FRAMEWORK.append(dummy_framework)
2423

25-
def read_report(self, temp, tests_num) -> dict:
24+
def read_report(self, temp) -> dict:
2625
"""
2726
Check if report file contains the given number of tests.
2827
"""
@@ -32,11 +31,9 @@ def read_report(self, temp, tests_num) -> dict:
3231

3332
# read report and check if all suite's tests have been executed
3433
report_d = None
35-
with open(report, 'r') as report_f:
34+
with open(report, 'r', encoding="utf-8") as report_f:
3635
report_d = json.loads(report_f.read())
3736

38-
assert len(report_d["results"]) == tests_num
39-
4037
return report_d
4138

4239
def test_wrong_options(self):
@@ -100,7 +97,8 @@ def test_run_suite(self, tmpdir):
10097

10198
assert excinfo.value.code == libkirk.main.RC_OK
10299

103-
self.read_report(temp, 2)
100+
report = self.read_report(temp)
101+
assert len(report["results"]) == 2
104102

105103
def test_run_suite_timeout(self, tmpdir):
106104
"""
@@ -119,8 +117,10 @@ def test_run_suite_timeout(self, tmpdir):
119117

120118
assert excinfo.value.code == libkirk.main.RC_OK
121119

122-
report_d = self.read_report(temp, 2)
123-
for param in report_d["results"]:
120+
report = self.read_report(temp)
121+
assert len(report["results"]) == 2
122+
123+
for param in report["results"]:
124124
assert param["test"]["passed"] == 0
125125
assert param["test"]["failed"] == 0
126126
assert param["test"]["broken"] == 0
@@ -186,7 +186,8 @@ def test_restore_suite(self, tmpdir):
186186

187187
assert excinfo.value.code == libkirk.main.RC_OK
188188

189-
self.read_report(temp, 2)
189+
report = self.read_report(temp)
190+
assert len(report["results"]) == 2
190191

191192
# restore session
192193
name = pwd.getpwuid(os.getuid()).pw_name
@@ -202,7 +203,8 @@ def test_restore_suite(self, tmpdir):
202203

203204
assert excinfo.value.code == libkirk.main.RC_OK
204205

205-
self.read_report(temp, 1)
206+
report = self.read_report(temp)
207+
assert len(report["results"]) == 1
206208

207209
def test_json_report(self, tmpdir):
208210
"""
@@ -223,9 +225,11 @@ def test_json_report(self, tmpdir):
223225
assert excinfo.value.code == libkirk.main.RC_OK
224226
assert os.path.isfile(report)
225227

226-
report_a = self.read_report(temp, 2)
228+
report_a = self.read_report(temp)
229+
assert len(report_a["results"]) == 2
230+
227231
report_b = None
228-
with open(report, 'r') as report_f:
232+
with open(report, 'r', encoding="utf-8") as report_f:
229233
report_b = json.loads(report_f.read())
230234

231235
assert report_a == report_b
@@ -247,7 +251,8 @@ def test_skip_tests(self, tmpdir):
247251

248252
assert excinfo.value.code == libkirk.main.RC_OK
249253

250-
self.read_report(temp, 1)
254+
report = self.read_report(temp)
255+
assert len(report["results"]) == 1
251256

252257
def test_skip_file(self, tmpdir):
253258
"""
@@ -269,7 +274,8 @@ def test_skip_file(self, tmpdir):
269274

270275
assert excinfo.value.code == libkirk.main.RC_OK
271276

272-
self.read_report(temp, 1)
277+
report = self.read_report(temp)
278+
assert len(report["results"]) == 1
273279

274280
def test_skip_tests_and_file(self, tmpdir):
275281
"""
@@ -292,7 +298,8 @@ def test_skip_tests_and_file(self, tmpdir):
292298

293299
assert excinfo.value.code == libkirk.main.RC_OK
294300

295-
self.read_report(temp, 1)
301+
report = self.read_report(temp)
302+
assert len(report["results"]) == 1
296303

297304
def test_workers(self, tmpdir):
298305
"""
@@ -312,7 +319,9 @@ def test_workers(self, tmpdir):
312319
libkirk.main.run(cmd_args=cmd_args)
313320

314321
assert excinfo.value.code == libkirk.main.RC_OK
315-
self.read_report(temp, 2)
322+
323+
report = self.read_report(temp)
324+
assert len(report["results"]) == 2
316325

317326
def test_sut_help(self):
318327
"""
@@ -360,8 +369,9 @@ def test_env(self, tmpdir):
360369

361370
assert excinfo.value.code == libkirk.main.RC_OK
362371

363-
report_d = self.read_report(temp, 1)
364-
assert report_d["results"][0]["test"]["log"] == "ciao"
372+
report = self.read_report(temp)
373+
assert len(report["results"]) == 1
374+
assert report["results"][0]["test"]["log"] == "ciao"
365375

366376
def test_suite_iterate(self, tmpdir):
367377
"""
@@ -380,7 +390,8 @@ def test_suite_iterate(self, tmpdir):
380390

381391
assert excinfo.value.code == libkirk.main.RC_OK
382392

383-
self.read_report(temp, 8)
393+
report = self.read_report(temp)
394+
assert len(report["results"]) == 8
384395

385396
def test_randomize(self, tmpdir):
386397
"""
@@ -402,10 +413,31 @@ def test_randomize(self, tmpdir):
402413

403414
assert excinfo.value.code == libkirk.main.RC_OK
404415

405-
report_d = self.read_report(temp, 2 * num_of_suites)
416+
report = self.read_report(temp)
417+
assert len(report["results"]) == 2 * num_of_suites
406418

407419
tests_names = []
408-
for test in report_d["results"]:
420+
for test in report["results"]:
409421
tests_names.append(test["test_fqn"])
410422

411423
assert ["test01", "test02"] * num_of_suites != tests_names
424+
425+
def test_runtime(self, tmpdir):
426+
"""
427+
Test --runtime option.
428+
"""
429+
temp = tmpdir.mkdir("temp")
430+
cmd_args = [
431+
"--tmp-dir", str(temp),
432+
"--framework", "dummy",
433+
"--run-suite", "suite01",
434+
"--runtime", "1",
435+
]
436+
437+
with pytest.raises(SystemExit) as excinfo:
438+
libkirk.main.run(cmd_args=cmd_args)
439+
440+
assert excinfo.value.code == libkirk.main.RC_OK
441+
442+
report = self.read_report(temp)
443+
assert len(report["results"]) > 2

libkirk/tests/test_session.py

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -163,3 +163,17 @@ async def test_run_randomize(self, tmpdir, session):
163163
tests_names.append(test["test_fqn"])
164164

165165
assert ["test01", "test02"] * num_of_suites != tests_names
166+
167+
async def test_run_runtime(self, tmpdir, session):
168+
"""
169+
Test run method when executing suites for a certain amount of time.
170+
"""
171+
report = str(tmpdir / "report.json")
172+
await session.run(
173+
suites=["suite01"],
174+
runtime=1,
175+
report_path=report)
176+
177+
with open(report, "r", encoding="utf-8") as report_file:
178+
report_data = json.loads(report_file.read())
179+
assert len(report_data["results"]) > 2

0 commit comments

Comments
 (0)