mirror of
https://github.com/bendtherules/pytest_gui_status.git
synced 2026-08-19 00:33:35 +00:00
Add minimal template+ add --gui_minimal + update docs
Custom templates wont be possible with this design
This commit is contained in:
@@ -8,6 +8,7 @@ import humanfriendly
|
||||
import os.path
|
||||
from ..utils import s
|
||||
from ..utils import REDIS_PORT
|
||||
from PyQt4.QtGui import QApplication
|
||||
|
||||
|
||||
class Controller(htmlPy.Object):
|
||||
@@ -19,12 +20,35 @@ class Controller(htmlPy.Object):
|
||||
"end": "Finished Tests"
|
||||
}
|
||||
|
||||
dict_tmpl = {
|
||||
"default": "index.html",
|
||||
"minimal": "minimal.html",
|
||||
}
|
||||
|
||||
dict_tmpl_size = {
|
||||
"default": (150, 80),
|
||||
"minimal": (50, 50)
|
||||
}
|
||||
|
||||
def __init__(self, app_gui):
|
||||
super(Controller, self).__init__()
|
||||
self.i = 0
|
||||
self.app_gui = app_gui
|
||||
self.last_state = None
|
||||
# Initialize the class here, if required.
|
||||
|
||||
self.tmpl_name_full = self.dict_tmpl.get(self.app_gui.tmpl_name)
|
||||
if self.tmpl_name_full is None:
|
||||
raise TypeError("template name must be valid, one of these: {allowed_tmpl_names}".format(
|
||||
allowed_tmpl_names=(", ".join(self.dict_tmpl.keys()))))
|
||||
|
||||
# set correct width, height
|
||||
# self.app_gui.window.minimumWidth, self.app_gui.window.minimumHeight = (0, 0)
|
||||
self.app_gui.width, self.app_gui.height = self.dict_tmpl_size.get(self.app_gui.tmpl_name)
|
||||
|
||||
screen_geo = QApplication.desktop().availableGeometry()
|
||||
screen_topright = screen_geo.topRight()
|
||||
self.app_gui.x_pos = (screen_topright.x() - 20) - self.app_gui.width
|
||||
self.app_gui.y_pos = (screen_topright.y() + 20)
|
||||
|
||||
@htmlPy.Slot()
|
||||
def redraw(self):
|
||||
@@ -78,6 +102,8 @@ class Controller(htmlPy.Object):
|
||||
dict_state["skip"] = s(redis_db.lrange("{hash_a}_skip".format(hash_a=hash_dir_name), 0, -1))
|
||||
|
||||
if (not self.last_state) or (self.last_state != dict_state):
|
||||
self.app_gui.html = render_template(self.app_gui, "index.html", dict_state)
|
||||
self.app_gui.title = u"{dir_name_topfolder} - Test Status".format(
|
||||
dir_name_topfolder=dict_state["dir_name_topfolder"])
|
||||
self.app_gui.html = render_template(self.app_gui, self.tmpl_name_full, dict_state)
|
||||
|
||||
self.last_state = dict_state
|
||||
|
||||
@@ -1,36 +1,46 @@
|
||||
import htmlPy
|
||||
import os
|
||||
import sys
|
||||
from PyQt4.QtGui import QApplication
|
||||
|
||||
import PyQt4.QtCore as QtCore
|
||||
import argparse
|
||||
|
||||
# Import back-end functionalities
|
||||
from gui_backend import Controller
|
||||
|
||||
|
||||
def main():
|
||||
if len(sys.argv) > 1:
|
||||
dir_name_raw = sys.argv[1]
|
||||
else:
|
||||
arg_parser = argparse.ArgumentParser()
|
||||
arg_parser.add_argument("--dir_name", help="root directory where py.test was executed")
|
||||
arg_parser.add_argument("--minimal", help="use minimal template", action="store_true")
|
||||
parsed_args = arg_parser.parse_args()
|
||||
|
||||
dir_name_raw = parsed_args.dir_name
|
||||
if dir_name_raw is None:
|
||||
dir_name_raw = "."
|
||||
dir_name = os.path.abspath(dir_name_raw)
|
||||
|
||||
if parsed_args.minimal:
|
||||
app_tmpl = "minimal"
|
||||
else:
|
||||
app_tmpl = "default"
|
||||
|
||||
# GUI initializations
|
||||
app = htmlPy.AppGUI(title=u"{dir_name} - Test Status".format(dir_name=dir_name),
|
||||
developer_mode=True, width=150, height=80)
|
||||
app.window.setWindowFlags(QtCore.Qt.WindowStaysOnTopHint)
|
||||
screen_geo = QApplication.desktop().availableGeometry()
|
||||
screen_topright = screen_geo.topRight()
|
||||
app.x_pos = (screen_topright.x() - 20) - app.width
|
||||
app.y_pos = (screen_topright.y() + 20)
|
||||
app = htmlPy.AppGUI(title=u"to_be_set_later",
|
||||
developer_mode=True, width=1, height=1)
|
||||
|
||||
app.window.setWindowFlags(QtCore.Qt.WindowTitleHint)
|
||||
# app.window.setWindowFlags(app.window.windowFlags() & ~QtCore.Qt.WindowMaximizeButtonHint)
|
||||
app.window.setWindowFlags(app.window.windowFlags() | QtCore.Qt.WindowStaysOnTopHint)
|
||||
|
||||
# GUI configarg
|
||||
BASE_DIR = os.path.abspath(os.path.dirname(__file__))
|
||||
app.static_path = os.path.join(BASE_DIR, "static/")
|
||||
app.template_path = os.path.join(BASE_DIR, "tmpl/")
|
||||
app.dir_name = dir_name
|
||||
app.tmpl_name = app_tmpl
|
||||
|
||||
# Register back-end functionalities
|
||||
# allow minimal tmpl with sys.arg
|
||||
app_backend = Controller(app)
|
||||
app.bind(app_backend)
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>{{dir_name}}</title>
|
||||
<title></title>
|
||||
<style>
|
||||
*
|
||||
{
|
||||
|
||||
@@ -0,0 +1,112 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title></title>
|
||||
<style>
|
||||
*
|
||||
{
|
||||
-webkit-box-sizing: border-box;
|
||||
-moz-box-sizing: border-box;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
body
|
||||
{
|
||||
margin: 2px;
|
||||
padding: 0;
|
||||
}
|
||||
.last-test-statusviz
|
||||
{
|
||||
width: 100%;
|
||||
height: 1.5em;
|
||||
}
|
||||
.statusdot
|
||||
{
|
||||
height: 100%;
|
||||
|
||||
width: 100%;
|
||||
/*width: 1em;*/
|
||||
padding: 1px;
|
||||
float: left;
|
||||
}
|
||||
.statusdot-fill
|
||||
{
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
.nostatusdot
|
||||
{
|
||||
padding: 1px;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background-color: yellow;
|
||||
}
|
||||
.fill-pass
|
||||
{
|
||||
background-color: green;
|
||||
}
|
||||
.fill-fail
|
||||
{
|
||||
background-color: red;
|
||||
}
|
||||
.last-test-statusviz
|
||||
{
|
||||
overflow: hidden;
|
||||
border: 2px solid black;
|
||||
}
|
||||
.last-test-timerelative
|
||||
{
|
||||
font-size: 0.75em;
|
||||
height: 1em;
|
||||
}
|
||||
.last-test-dirname
|
||||
{
|
||||
font-size: 1em;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
</style>
|
||||
<!-- <script type="text/javascript" src="./refresh.js"></script> -->
|
||||
<script type="text/javascript">
|
||||
// debugger
|
||||
document.onload = setInterval(function(){Controller.redraw()},1000)
|
||||
</script>
|
||||
</head>
|
||||
<body>
|
||||
<div class="section-last-test">
|
||||
<!-- <div class="state">
|
||||
{{ state_desc }}
|
||||
</div>
|
||||
<div class="last-test-statusviz">
|
||||
{% for testname in collect %}
|
||||
<div class="statusdot statusdot-{{loop.index0}}">
|
||||
{% if testname in pass %}
|
||||
<div class="statusdot-fill fill-pass"></div>
|
||||
{% elif testname in fail %}
|
||||
<div class="statusdot-fill fill-fail"></div>
|
||||
{% endif %}
|
||||
</div>
|
||||
{% endfor %}
|
||||
</div>
|
||||
<div class="last-test-timerelative">
|
||||
Got {{ last_updated_friendly }} ago
|
||||
</div> -->
|
||||
<div class="last-test-dirname">
|
||||
{{ dir_name_topfolder }}
|
||||
</div>
|
||||
<div class="last-test-statusviz">
|
||||
{% if state == "end" %}
|
||||
<div class="statusdot statusdot-{{loop.index0}}">
|
||||
{% if (fail|length) == 0 %}
|
||||
<div class="statusdot-fill fill-pass"></div>
|
||||
{% else %}
|
||||
<div class="statusdot-fill fill-fail"></div>
|
||||
{% endif %}
|
||||
</div>
|
||||
{% else %}
|
||||
<div class="nostatusdot"></div>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,12 +1,12 @@
|
||||
Todo
|
||||
------
|
||||
|
||||
6. Allow config for template
|
||||
1. test template path available after install
|
||||
2. test option --show_status_gui available
|
||||
3. add details of --show_status_gui in addoption
|
||||
4. Release on pypi
|
||||
5. Add well-explained readme
|
||||
6. Allow config for template
|
||||
|
||||
7. use logging.debug / log file for more prints
|
||||
8. Tests with setup/teardown/class when needed
|
||||
|
||||
@@ -71,7 +71,7 @@ class Helpers(object):
|
||||
Helpers.modify_last_updated(dir_name)
|
||||
|
||||
@staticmethod
|
||||
def start_gui(dir_name):
|
||||
def start_gui(dir_name, extra_args=None):
|
||||
'''
|
||||
Init status_gui at start
|
||||
'''
|
||||
@@ -88,6 +88,9 @@ class Helpers(object):
|
||||
if not (existing_gui_pid and psutil.pid_exists(existing_gui_pid)):
|
||||
norm_dir_name = os.path.normpath(dir_name)
|
||||
command_status_gui = command_status_gui_gen.format(norm_dir_name=norm_dir_name)
|
||||
if extra_args:
|
||||
command_status_gui = command_status_gui + " " + extra_args
|
||||
# print("Starting gui as: {cmd_gui}".format(cmd_gui=command_status_gui))
|
||||
gui_popen_obj = subprocess.Popen(command_status_gui)
|
||||
gui_pid = gui_popen_obj.pid
|
||||
redis_db.set("{hash_a}_gui_pid".format(hash_a=hash_dir_name), gui_pid)
|
||||
@@ -202,7 +205,8 @@ class PYTEST_DATA(object):
|
||||
|
||||
|
||||
def pytest_addoption(parser):
|
||||
parser.addoption("--show_status_gui", dest="show_status_gui", action="store_true")
|
||||
parser.addoption("--gui", dest="show_status_gui", action="store_true")
|
||||
parser.addoption("--gui_minimal", dest="show_status_gui_minimal", action="store_true")
|
||||
|
||||
|
||||
def pytest_configure(config):
|
||||
@@ -218,6 +222,8 @@ def pytest_sessionstart(session):
|
||||
|
||||
if config.getoption("show_status_gui"):
|
||||
Helpers.start_gui(PYTEST_DATA.data["dir_name_start"])
|
||||
elif config.getoption("show_status_gui_minimal"):
|
||||
Helpers.start_gui(PYTEST_DATA.data["dir_name_start"], extra_args="--minimal")
|
||||
|
||||
|
||||
def pytest_collectstart(collector):
|
||||
|
||||
@@ -14,7 +14,7 @@ command_redis_server = command_redis_server_gen.format(REDIS_PATH=REDIS_PATH,
|
||||
REDIS_ARGS=REDIS_ARGS,
|
||||
REDIS_PORT=REDIS_PORT)
|
||||
|
||||
command_status_gui_gen = "pytest_gui_status \"{norm_dir_name}\""
|
||||
command_status_gui_gen = "pytest_gui_status --dir_name=\"{norm_dir_name}\""
|
||||
|
||||
|
||||
def s(input_):
|
||||
|
||||
Reference in New Issue
Block a user