Skip to content

Commit ef20ec3

Browse files
authored
Fix/timeline plots of driver-info feature (#1211)
1 parent b048d93 commit ef20ec3

3 files changed

Lines changed: 52 additions & 38 deletions

File tree

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Fix an issue that generated incorrect figures of driver starting/stopping timeline inside the driver-info feature.

testplan/testing/base.py

Lines changed: 33 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
import subprocess
66
import sys
77
import warnings
8-
from datetime import timezone
8+
from datetime import datetime, timezone
99
from enum import Enum
1010
from typing import (
1111
Callable,
@@ -817,42 +817,43 @@ def _record_driver_timing(
817817
stdout_style=self.stdout_style, _scratch=self.scratch
818818
)
819819

820-
def _try_asutc(dt_or_none):
820+
def _try_asutc(dt_or_none: Optional[datetime]) -> Optional[datetime]:
821821
if dt_or_none:
822822
return dt_or_none.astimezone(tz=timezone.utc)
823823
return None
824824

825+
# column names
826+
D_CLASS = "Driver Class"
827+
D_NAME = "Driver Name"
828+
START_TIME = "Start Time (UTC)"
829+
END_TIME = "Stop Time (UTC)"
830+
DURATION = "Duration(seconds)"
831+
825832
# input for tablelog
826833
table = [
827834
{
828-
"Driver Class": driver.__class__.__name__,
829-
"Driver Name": driver.name,
830-
"Start Time (UTC)": _try_asutc(
835+
D_CLASS: driver.__class__.__name__,
836+
D_NAME: driver.name,
837+
START_TIME: _try_asutc(
831838
driver.timer.last(setup_or_teardown).start
832839
),
833-
"Stop Time (UTC)": _try_asutc(
834-
driver.timer.last(setup_or_teardown).end
835-
),
836-
"Duration(seconds)": driver.timer.last(
837-
setup_or_teardown
838-
).elapsed,
840+
END_TIME: _try_asutc(driver.timer.last(setup_or_teardown).end),
841+
DURATION: driver.timer.last(setup_or_teardown).elapsed,
839842
}
840843
for driver in self.resources
841844
if setup_or_teardown in driver.timer.keys()
842845
]
843-
table.sort(key=lambda entry: entry["Start Time (UTC)"])
846+
table.sort(key=lambda entry: entry[START_TIME])
844847

845848
def _format_start_stop_time(d):
846849
# format tablelog entries to be human readable
847-
if d["Start Time (UTC)"]:
848-
d["Start Time (UTC)"] = d["Start Time (UTC)"].strftime(
849-
"%H:%M:%S.%f"
850-
)
851-
if d["Stop Time (UTC)"]:
852-
d["Stop Time (UTC)"] = d["Stop Time (UTC)"].strftime(
853-
"%H:%M:%S.%f"
854-
)
855-
return d
850+
st = (
851+
d[START_TIME].strftime("%H:%M:%S.%f")
852+
if d[START_TIME]
853+
else None
854+
)
855+
et = d[END_TIME].strftime("%H:%M:%S.%f") if d[END_TIME] else None
856+
return {**d, START_TIME: st, END_TIME: et}
856857

857858
case_result.table.log(
858859
[_format_start_stop_time(d) for d in table],
@@ -870,32 +871,28 @@ def _format_start_stop_time(d):
870871
else:
871872
# input for plotly
872873
px_input = {
873-
"Start Time (UTC)": [],
874-
"Stop Time (UTC)": [],
875-
"Driver Name": [],
874+
D_NAME: [],
875+
START_TIME: [],
876+
END_TIME: [],
876877
}
877878
for driver in table:
878-
if driver["Stop Time (UTC)"]:
879-
px_input["Driver Name"].append(driver["Driver Name"])
880-
px_input["Start Time (UTC)"].append(
881-
driver["Start Time (UTC)"]
882-
)
883-
px_input["Stop Time (UTC)"].append(
884-
driver["Stop Time (UTC)"]
885-
)
879+
if driver[END_TIME]:
880+
px_input[D_NAME].append(driver[D_NAME])
881+
px_input[START_TIME].append(driver[START_TIME])
882+
px_input[END_TIME].append(driver[END_TIME])
886883

887884
# empirical values
888885
padding = 150
889886
row_size = 25
890-
height = padding + row_size * len(px_input["Driver Name"])
887+
height = padding + row_size * len(px_input[D_NAME])
891888
if height == padding:
892889
# min height
893890
height = padding + row_size
894891
fig = px.timeline(
895892
px_input,
896-
x_start="Start Time (UTC)",
897-
x_end="Stop Time (UTC)",
898-
y="Driver Name",
893+
x_start=START_TIME,
894+
x_end=END_TIME,
895+
y=D_NAME,
899896
height=height,
900897
)
901898
fig.update_yaxes(autorange="reversed", automargin=True)

tests/functional/testplan/testing/multitest/test_driver_info.py

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,13 @@
22

33
pytest.importorskip("plotly", reason="expected report generated with plotly")
44

5+
import numpy as np
6+
57
from testplan.common.utils.context import context
68
from testplan.testing.multitest import MultiTest
79
from testplan.testing.multitest.driver.base import Driver
810
from testplan.testing.multitest.driver.tcp import TCPServer, TCPClient
9-
11+
from testplan.testing.multitest.entries.base import Plotly
1012
from testplan.common.utils.testing import check_report
1113

1214
from ..fixtures import base
@@ -17,6 +19,9 @@ def started_check(self):
1719
raise Exception
1820

1921

22+
orig_init = Plotly.__init__
23+
24+
2025
def test_driver_info_flag(mockplan):
2126
expected_report = (
2227
base.passing.report.expected_report_with_driver_and_driver_info_flag
@@ -47,7 +52,7 @@ def test_failing_driver_with_driver_info_flag(mockplan):
4752
check_report(expected=expected_report, actual=mockplan.report)
4853

4954

50-
def test_multitest_drivers_connection_in_testplan(mockplan):
55+
def test_multitest_drivers_connection_in_testplan(mocker, mockplan):
5156
expected_report = base.passing.report.expected_report_with_driver_connections_and_driver_info_flag
5257
server = TCPServer("server")
5358
client = TCPClient(
@@ -62,6 +67,17 @@ def test_multitest_drivers_connection_in_testplan(mockplan):
6267
)
6368
mtest.cfg.set_local("driver_info", True)
6469
mockplan.add(mtest)
70+
71+
def fig_data_tc_plotly_init(that, fig, *args, **kwargs):
72+
assert np.issubdtype(fig.data[0].base.dtype, np.datetime64)
73+
orig_init(that, fig, *args, **kwargs)
74+
75+
mocker.patch.object(
76+
Plotly,
77+
"__init__",
78+
new=fig_data_tc_plotly_init,
79+
)
6580
assert mockplan.run().run is True
81+
mocker.resetall()
6682

6783
check_report(expected=expected_report, actual=mockplan.report)

0 commit comments

Comments
 (0)