From a2329249344727de4f65c5735afc69f16967faf2 Mon Sep 17 00:00:00 2001 From: Abhas Bhattacharya Date: Sun, 13 Dec 2015 09:09:33 +0530 Subject: [PATCH 1/3] Move direct folders into modulenamed folder as subfolder --- pytest_gui_status/status_gui/__init__.py | 0 pytest_gui_status/status_gui/gui.py | 0 pytest_gui_status/status_plugin/__init__.py | 0 pytest_gui_status/status_plugin/plugin.py | 201 ++++++++++++++++++++ 4 files changed, 201 insertions(+) create mode 100644 pytest_gui_status/status_gui/__init__.py create mode 100644 pytest_gui_status/status_gui/gui.py create mode 100644 pytest_gui_status/status_plugin/__init__.py create mode 100644 pytest_gui_status/status_plugin/plugin.py diff --git a/pytest_gui_status/status_gui/__init__.py b/pytest_gui_status/status_gui/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/pytest_gui_status/status_gui/gui.py b/pytest_gui_status/status_gui/gui.py new file mode 100644 index 0000000..e69de29 diff --git a/pytest_gui_status/status_plugin/__init__.py b/pytest_gui_status/status_plugin/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/pytest_gui_status/status_plugin/plugin.py b/pytest_gui_status/status_plugin/plugin.py new file mode 100644 index 0000000..33e313d --- /dev/null +++ b/pytest_gui_status/status_plugin/plugin.py @@ -0,0 +1,201 @@ +import shlex +import subprocess +import time +import sys +import redis + +REDIS_PORT = 5946 + +command_redis_server_gen = "redis-server --port {port} --maxheap 20MB" +command_redis_server = command_redis_server_gen.format(port=REDIS_PORT) + +# Redis will look like: +# PYTEST_STATUS_DB = 1 +# directories_to_hash = {"dir_a":hash_a,"dir_b":hash_b} +# {hash_a}_state = "start" / "collect" / "runtest" / "end" +# {hash_a}_last_updated = 2015-12-12T20:50:16.056000 # isoformat +# output - datetime.datetime.now().isoformat() +# input - dateutil.parser.parse() +# {hash_a}_collect = [test_a_name, test_b_name,...] +# {hash_a}_pass = [test_a_name,...] +# {hash_a}_fail = [test_b_name,...] +# {hash_a}_skip = [test_c_name,...] + + +class Helpers(object): + + @staticmethod + def on_start(dir_name): + ''' + Init gui_status and redis on start of pytest. + + dir_name - Name of directory from which pytest started + ''' + command_redis_server_args = shlex.split(command_redis_server) + print(command_redis_server_args) + + print("Starting up redis") + redis_popen_obj = subprocess.Popen(command_redis_server_args) + + # wait and check if redis has not exited yet + time.sleep(1) + if redis_popen_obj.poll() is None: + print("Started successfully redis") + else: + print("Redis couldnt start there, trying to check if already running on that port") + redis_db = redis.StrictRedis(host='localhost', port=REDIS_PORT, db=0) + if redis_db.ping() and redis_db.get("PYTEST_STATUS_DB") == "1": + print("Yup, it was already running") + else: + print("** Not found existing redis, couldnt connect, check! **") + sys.exit() + + # todo : start and check gui with dir name and hash + + # craete redis connection and set sample key + redis_db = redis.StrictRedis(host='localhost', port=REDIS_PORT, db=0) + redis_db.set("PYTEST_STATUS_DB", "1") + + hash_dir_name = hash(dir_name) + redis_db.hset("directories_to_hash", dir_name, hash_dir_name) + Helpers.on_start_reset(dir_name) + + redis_db.set("{hash_a}_state".format(hash_a=hash_dir_name), "start") + + # set last updated + Helpers.modify_last_updated(dir_name) + + @staticmethod + def on_collectstart(dir_name): + # craete redis connection + redis_db = redis.StrictRedis(host='localhost', port=REDIS_PORT, db=0) + + hash_dir_name = redis_db.hget("directories_to_hash", dir_name) + + redis_db.set("{hash_a}_state".format(hash_a=hash_dir_name), "collect") + + # set last updated + Helpers.modify_last_updated(dir_name) + + @staticmethod + def on_collectend(dir_name, list_test_name): + # craete redis connection + redis_db = redis.StrictRedis(host='localhost', port=REDIS_PORT, db=0) + + hash_dir_name = redis_db.hget("directories_to_hash", dir_name) + + redis_db.rpush("{hash_a}_collect".format(hash_a=hash_dir_name), *list_test_name) + + # set last updated + Helpers.modify_last_updated(dir_name) + + @staticmethod + def on_test_eachstart(dir_name): + # craete redis connection + redis_db = redis.StrictRedis(host='localhost', port=REDIS_PORT, db=0) + + hash_dir_name = redis_db.hget("directories_to_hash", dir_name) + + redis_db.set("{hash_a}_state".format(hash_a=hash_dir_name), "runtest") + + # set last updated + Helpers.modify_last_updated(dir_name) + + @staticmethod + def on_test_eachend(dir_name, list_test_result): + # craete redis connection + redis_db = redis.StrictRedis(host='localhost', port=REDIS_PORT, db=0) + + hash_dir_name = redis_db.hget("directories_to_hash", dir_name) + + list_testname_pass = [test_result.nodeid for test_result in + list_test_result if test_result.outcome == "passed"] + + list_testname_fail = [test_result.nodeid for test_result in + list_test_result if test_result.outcome == "failed"] + + list_testname_skip = [test_result.nodeid for test_result in + list_test_result if test_result.outcome == "skipped"] + + if list_testname_pass: + redis_db.lpush("{hash_a}_pass".format(hash_a=hash_dir_name), *list_testname_pass) + if list_testname_fail: + redis_db.lpush("{hash_a}_fail".format(hash_a=hash_dir_name), *list_testname_fail) + if list_testname_skip: + redis_db.lpush("{hash_a}_skip".format(hash_a=hash_dir_name), *list_testname_skip) + + # set last updated + Helpers.modify_last_updated(dir_name) + + @staticmethod + def on_end(dir_name): + # craete redis connection + redis_db = redis.StrictRedis(host='localhost', port=REDIS_PORT, db=0) + + hash_dir_name = redis_db.hget("directories_to_hash", dir_name) + + redis_db.set("{hash_a}_state".format(hash_a=hash_dir_name), "end") + + # set last updated + Helpers.modify_last_updated(dir_name) + + @staticmethod + def on_start_reset(dir_name): + redis_db = redis.StrictRedis(host='localhost', port=REDIS_PORT, db=0) + hash_dir_name = redis_db.hget("directories_to_hash", dir_name) + + list_gen_varname = ["{hash_a}_state", "{hash_a}_last_updated", "{hash_a}_collect", "{hash_a}_pass", "{hash_a}_fail", "{hash_a}_skip"] + list_cur_varname = [varname.format(hash_a=hash_dir_name) for varname in list_gen_varname] + del list_gen_varname + + redis_db.delete(*list_cur_varname) + + @staticmethod + def modify_last_updated(dir_name): + import datetime + redis_db = redis.StrictRedis(host='localhost', port=REDIS_PORT, db=0) + hash_dir_name = redis_db.hget("directories_to_hash", dir_name) + + cur_iso_datetime = datetime.datetime.now().isoformat() + + redis_db.set("{hash_a}_last_updated".format(hash_a=hash_dir_name), cur_iso_datetime) + + +# Start here +class PYTEST_DATA(object): + data = {} + + +def pytest_sessionstart(session): + PYTEST_DATA.data["dir_name_start"] = session.startdir + Helpers.on_start(PYTEST_DATA.data["dir_name_start"]) + + +def pytest_collectstart(collector): + Helpers.on_collectstart(PYTEST_DATA.data["dir_name_start"]) + + +def pytest_itemcollected(item): + Helpers.on_collectend(PYTEST_DATA.data["dir_name_start"], [item.nodeid]) + + +def pytest_runtest_logstart(nodeid, location): + Helpers.on_test_eachstart(PYTEST_DATA.data["dir_name_start"]) + + +def pytest_runtest_logreport(report): + if report.when == "call": + Helpers.on_test_eachend(PYTEST_DATA.data["dir_name_start"], [report]) + + +def pytest_sessionfinish(session, exitstatus): + Helpers.on_end(PYTEST_DATA.data["dir_name_start"]) + +# pytest_sessionstart(session) +# pytest_collectstart(collector) | collector.config +# pytest_itemcollected +## pytest_collection_modifyitems(session, config, items) +# pytest_collectreport +# pytest_runtest_logstart(nodeid, location) - single test start +# pytest_runtest_logreport(report) - single test end +# pytest_sessionfinish(session, exit_status) - session end From c13240e8572effe354370b166813620ff910b413 Mon Sep 17 00:00:00 2001 From: Abhas Bhattacharya Date: Sun, 13 Dec 2015 09:11:52 +0530 Subject: [PATCH 2/3] Clear diect folders, part of previous commit --- status_gui/__init__.py | 0 status_gui/gui.py | 0 status_plugin/__init__.py | 0 status_plugin/plugin.py | 201 -------------------------------------- 4 files changed, 201 deletions(-) delete mode 100644 status_gui/__init__.py delete mode 100644 status_gui/gui.py delete mode 100644 status_plugin/__init__.py delete mode 100644 status_plugin/plugin.py diff --git a/status_gui/__init__.py b/status_gui/__init__.py deleted file mode 100644 index e69de29..0000000 diff --git a/status_gui/gui.py b/status_gui/gui.py deleted file mode 100644 index e69de29..0000000 diff --git a/status_plugin/__init__.py b/status_plugin/__init__.py deleted file mode 100644 index e69de29..0000000 diff --git a/status_plugin/plugin.py b/status_plugin/plugin.py deleted file mode 100644 index 33e313d..0000000 --- a/status_plugin/plugin.py +++ /dev/null @@ -1,201 +0,0 @@ -import shlex -import subprocess -import time -import sys -import redis - -REDIS_PORT = 5946 - -command_redis_server_gen = "redis-server --port {port} --maxheap 20MB" -command_redis_server = command_redis_server_gen.format(port=REDIS_PORT) - -# Redis will look like: -# PYTEST_STATUS_DB = 1 -# directories_to_hash = {"dir_a":hash_a,"dir_b":hash_b} -# {hash_a}_state = "start" / "collect" / "runtest" / "end" -# {hash_a}_last_updated = 2015-12-12T20:50:16.056000 # isoformat -# output - datetime.datetime.now().isoformat() -# input - dateutil.parser.parse() -# {hash_a}_collect = [test_a_name, test_b_name,...] -# {hash_a}_pass = [test_a_name,...] -# {hash_a}_fail = [test_b_name,...] -# {hash_a}_skip = [test_c_name,...] - - -class Helpers(object): - - @staticmethod - def on_start(dir_name): - ''' - Init gui_status and redis on start of pytest. - - dir_name - Name of directory from which pytest started - ''' - command_redis_server_args = shlex.split(command_redis_server) - print(command_redis_server_args) - - print("Starting up redis") - redis_popen_obj = subprocess.Popen(command_redis_server_args) - - # wait and check if redis has not exited yet - time.sleep(1) - if redis_popen_obj.poll() is None: - print("Started successfully redis") - else: - print("Redis couldnt start there, trying to check if already running on that port") - redis_db = redis.StrictRedis(host='localhost', port=REDIS_PORT, db=0) - if redis_db.ping() and redis_db.get("PYTEST_STATUS_DB") == "1": - print("Yup, it was already running") - else: - print("** Not found existing redis, couldnt connect, check! **") - sys.exit() - - # todo : start and check gui with dir name and hash - - # craete redis connection and set sample key - redis_db = redis.StrictRedis(host='localhost', port=REDIS_PORT, db=0) - redis_db.set("PYTEST_STATUS_DB", "1") - - hash_dir_name = hash(dir_name) - redis_db.hset("directories_to_hash", dir_name, hash_dir_name) - Helpers.on_start_reset(dir_name) - - redis_db.set("{hash_a}_state".format(hash_a=hash_dir_name), "start") - - # set last updated - Helpers.modify_last_updated(dir_name) - - @staticmethod - def on_collectstart(dir_name): - # craete redis connection - redis_db = redis.StrictRedis(host='localhost', port=REDIS_PORT, db=0) - - hash_dir_name = redis_db.hget("directories_to_hash", dir_name) - - redis_db.set("{hash_a}_state".format(hash_a=hash_dir_name), "collect") - - # set last updated - Helpers.modify_last_updated(dir_name) - - @staticmethod - def on_collectend(dir_name, list_test_name): - # craete redis connection - redis_db = redis.StrictRedis(host='localhost', port=REDIS_PORT, db=0) - - hash_dir_name = redis_db.hget("directories_to_hash", dir_name) - - redis_db.rpush("{hash_a}_collect".format(hash_a=hash_dir_name), *list_test_name) - - # set last updated - Helpers.modify_last_updated(dir_name) - - @staticmethod - def on_test_eachstart(dir_name): - # craete redis connection - redis_db = redis.StrictRedis(host='localhost', port=REDIS_PORT, db=0) - - hash_dir_name = redis_db.hget("directories_to_hash", dir_name) - - redis_db.set("{hash_a}_state".format(hash_a=hash_dir_name), "runtest") - - # set last updated - Helpers.modify_last_updated(dir_name) - - @staticmethod - def on_test_eachend(dir_name, list_test_result): - # craete redis connection - redis_db = redis.StrictRedis(host='localhost', port=REDIS_PORT, db=0) - - hash_dir_name = redis_db.hget("directories_to_hash", dir_name) - - list_testname_pass = [test_result.nodeid for test_result in - list_test_result if test_result.outcome == "passed"] - - list_testname_fail = [test_result.nodeid for test_result in - list_test_result if test_result.outcome == "failed"] - - list_testname_skip = [test_result.nodeid for test_result in - list_test_result if test_result.outcome == "skipped"] - - if list_testname_pass: - redis_db.lpush("{hash_a}_pass".format(hash_a=hash_dir_name), *list_testname_pass) - if list_testname_fail: - redis_db.lpush("{hash_a}_fail".format(hash_a=hash_dir_name), *list_testname_fail) - if list_testname_skip: - redis_db.lpush("{hash_a}_skip".format(hash_a=hash_dir_name), *list_testname_skip) - - # set last updated - Helpers.modify_last_updated(dir_name) - - @staticmethod - def on_end(dir_name): - # craete redis connection - redis_db = redis.StrictRedis(host='localhost', port=REDIS_PORT, db=0) - - hash_dir_name = redis_db.hget("directories_to_hash", dir_name) - - redis_db.set("{hash_a}_state".format(hash_a=hash_dir_name), "end") - - # set last updated - Helpers.modify_last_updated(dir_name) - - @staticmethod - def on_start_reset(dir_name): - redis_db = redis.StrictRedis(host='localhost', port=REDIS_PORT, db=0) - hash_dir_name = redis_db.hget("directories_to_hash", dir_name) - - list_gen_varname = ["{hash_a}_state", "{hash_a}_last_updated", "{hash_a}_collect", "{hash_a}_pass", "{hash_a}_fail", "{hash_a}_skip"] - list_cur_varname = [varname.format(hash_a=hash_dir_name) for varname in list_gen_varname] - del list_gen_varname - - redis_db.delete(*list_cur_varname) - - @staticmethod - def modify_last_updated(dir_name): - import datetime - redis_db = redis.StrictRedis(host='localhost', port=REDIS_PORT, db=0) - hash_dir_name = redis_db.hget("directories_to_hash", dir_name) - - cur_iso_datetime = datetime.datetime.now().isoformat() - - redis_db.set("{hash_a}_last_updated".format(hash_a=hash_dir_name), cur_iso_datetime) - - -# Start here -class PYTEST_DATA(object): - data = {} - - -def pytest_sessionstart(session): - PYTEST_DATA.data["dir_name_start"] = session.startdir - Helpers.on_start(PYTEST_DATA.data["dir_name_start"]) - - -def pytest_collectstart(collector): - Helpers.on_collectstart(PYTEST_DATA.data["dir_name_start"]) - - -def pytest_itemcollected(item): - Helpers.on_collectend(PYTEST_DATA.data["dir_name_start"], [item.nodeid]) - - -def pytest_runtest_logstart(nodeid, location): - Helpers.on_test_eachstart(PYTEST_DATA.data["dir_name_start"]) - - -def pytest_runtest_logreport(report): - if report.when == "call": - Helpers.on_test_eachend(PYTEST_DATA.data["dir_name_start"], [report]) - - -def pytest_sessionfinish(session, exitstatus): - Helpers.on_end(PYTEST_DATA.data["dir_name_start"]) - -# pytest_sessionstart(session) -# pytest_collectstart(collector) | collector.config -# pytest_itemcollected -## pytest_collection_modifyitems(session, config, items) -# pytest_collectreport -# pytest_runtest_logstart(nodeid, location) - single test start -# pytest_runtest_logreport(report) - single test end -# pytest_sessionfinish(session, exit_status) - session end From 02f0a440a02792ec4d44f1025a555723ff725ce1 Mon Sep 17 00:00:00 2001 From: Abhas Bhattacharya Date: Fri, 18 Dec 2015 23:06:38 +0530 Subject: [PATCH 3/3] Add 2 full tests for plugin + use env port for test --- pytest.ini | 2 + pytest_gui_status/status_plugin/__init__.py | 1 + pytest_gui_status/status_plugin/plugin.py | 7 +- tests/test_plugin.py | 94 +++++++++++++++++++++ tests/testcases/case_1/conftest.py | 1 + tests/testcases/case_1/test_1.py | 6 ++ tests/testcases/case_2/conftest.py | 1 + tests/testcases/case_2/test_1.py | 17 ++++ 8 files changed, 128 insertions(+), 1 deletion(-) create mode 100644 pytest.ini create mode 100644 tests/test_plugin.py create mode 100644 tests/testcases/case_1/conftest.py create mode 100644 tests/testcases/case_1/test_1.py create mode 100644 tests/testcases/case_2/conftest.py create mode 100644 tests/testcases/case_2/test_1.py diff --git a/pytest.ini b/pytest.ini new file mode 100644 index 0000000..f08c317 --- /dev/null +++ b/pytest.ini @@ -0,0 +1,2 @@ +[pytest] +norecursedirs = .* pytest_gui_status testcases diff --git a/pytest_gui_status/status_plugin/__init__.py b/pytest_gui_status/status_plugin/__init__.py index e69de29..48aad58 100644 --- a/pytest_gui_status/status_plugin/__init__.py +++ b/pytest_gui_status/status_plugin/__init__.py @@ -0,0 +1 @@ +from .plugin import * diff --git a/pytest_gui_status/status_plugin/plugin.py b/pytest_gui_status/status_plugin/plugin.py index 33e313d..ed72779 100644 --- a/pytest_gui_status/status_plugin/plugin.py +++ b/pytest_gui_status/status_plugin/plugin.py @@ -3,8 +3,13 @@ import subprocess import time import sys import redis +import os -REDIS_PORT = 5946 +env_redis_port = os.environ.get("pytest_status_port") +if env_redis_port: + REDIS_PORT = int(env_redis_port) +else: + REDIS_PORT = 5946 command_redis_server_gen = "redis-server --port {port} --maxheap 20MB" command_redis_server = command_redis_server_gen.format(port=REDIS_PORT) diff --git a/tests/test_plugin.py b/tests/test_plugin.py new file mode 100644 index 0000000..68b62b0 --- /dev/null +++ b/tests/test_plugin.py @@ -0,0 +1,94 @@ +import pytest_gui_status.status_plugin as status_plugin +import subprocess +from mock import patch +import redis +import pytest + +import os +import tempfile +import shutil + +REDIS_TEST_PORT = status_plugin.REDIS_PORT + 1 + + +class patched_chdir(object): + + """Just like chdir, but can be used in `with` - sets back the old path at exit""" + + def __init__(self, new_path): + self.old_path = os.getcwd() + self.new_path = new_path + + def __enter__(self): + os.chdir(self.new_path) + + def __exit__(self, type, value, traceback): + os.chdir(self.old_path) + + +def create_temp_case(case_name, path_tmpdir=None): + with patched_chdir(os.path.dirname(__file__)): + path_test_cases = os.path.abspath("testcases/") + path_case = os.path.join(path_test_cases, case_name) + + path_tmpdir = path_tmpdir or tempfile.mkdtemp() + path_tmpdir_case = os.path.join(path_tmpdir, case_name) + shutil.copytree(path_case, path_tmpdir_case) + + return path_tmpdir_case + + +@patch.dict("os.environ", + {"pytest_status_port": str(REDIS_TEST_PORT)}) +def test_whole_1(tmpdir): + ''' + Integration test + ''' + os.chdir(os.path.dirname(__file__)) + tmpdir = str(tmpdir) + path_case = create_temp_case("case_1", tmpdir) + os.chdir(path_case) + + assert(os.environ.get("pytest_status_port") == str(REDIS_TEST_PORT)) + + popen_pytest = subprocess.Popen(["py.test", "-s"], shell=True) + popen_pytest.wait() + + # pytest.main(["-s"]) + + dir_name = os.getcwd() + assert (dir_name == path_case) + redis_db = redis.StrictRedis(host='localhost', port=REDIS_TEST_PORT, db=0) + hash_dir_name = redis_db.hget("directories_to_hash", dir_name) + + assert (redis_db.llen("{hash_a}_pass".format(hash_a=hash_dir_name)) == 1) + assert (redis_db.llen("{hash_a}_fail".format(hash_a=hash_dir_name)) == 1) + assert (redis_db.llen("{hash_a}_skip".format(hash_a=hash_dir_name)) == 0) + + collected_tests = redis_db.lrange("{hash_a}_collect".format(hash_a=hash_dir_name), 0, -1) + assert (collected_tests == ["test_1.py::test_pass", "test_1.py::test_fail"]) + + +@patch.dict("os.environ", + {"pytest_status_port": str(REDIS_TEST_PORT)}) +def test_whole_2(tmpdir): + ''' + Integration test + ''' + os.chdir(os.path.dirname(__file__)) + tmpdir = str(tmpdir) + path_case = create_temp_case("case_2", tmpdir) + os.chdir(path_case) + + popen_pytest = subprocess.Popen(["py.test", "-s"], shell=True) + popen_pytest.wait() + + # pytest.main(["-s"]) + + dir_name = path_case + redis_db = redis.StrictRedis(host='localhost', port=REDIS_TEST_PORT, db=0) + hash_dir_name = redis_db.hget("directories_to_hash", dir_name) + + assert (redis_db.llen("{hash_a}_pass".format(hash_a=hash_dir_name)) == 1) + assert (redis_db.llen("{hash_a}_fail".format(hash_a=hash_dir_name)) == 2) + assert (redis_db.llen("{hash_a}_skip".format(hash_a=hash_dir_name)) == 1) diff --git a/tests/testcases/case_1/conftest.py b/tests/testcases/case_1/conftest.py new file mode 100644 index 0000000..3808850 --- /dev/null +++ b/tests/testcases/case_1/conftest.py @@ -0,0 +1 @@ +pytest_plugins = "pytest_gui_status.status_plugin" diff --git a/tests/testcases/case_1/test_1.py b/tests/testcases/case_1/test_1.py new file mode 100644 index 0000000..a1feafa --- /dev/null +++ b/tests/testcases/case_1/test_1.py @@ -0,0 +1,6 @@ +def test_pass(): + assert 1 + + +def test_fail(): + assert 0 diff --git a/tests/testcases/case_2/conftest.py b/tests/testcases/case_2/conftest.py new file mode 100644 index 0000000..3808850 --- /dev/null +++ b/tests/testcases/case_2/conftest.py @@ -0,0 +1 @@ +pytest_plugins = "pytest_gui_status.status_plugin" diff --git a/tests/testcases/case_2/test_1.py b/tests/testcases/case_2/test_1.py new file mode 100644 index 0000000..b1cef33 --- /dev/null +++ b/tests/testcases/case_2/test_1.py @@ -0,0 +1,17 @@ +import pytest + + +def test_pass_1(): + assert 1 + + +def test_fail_1(): + assert 0 + + +def test_fail_2(): + assert 0 + + +def test_skip_1(): + pytest.skip()