Skip to content

Commit af328ba

Browse files
committed
feat: start integrating to pytest-cov
Start using the .coverage file from pytest-cov for rts
1 parent be1c42e commit af328ba

15 files changed

+146
-996
lines changed

pytest_rts/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,2 @@
11
"""pytest-rts: avoid already imported warning: PYTEST_DONT_REWRITE"""
2-
__version__ = "1.2.1"
2+
__version__ = "2.0.0"

pytest_rts/collect.py

Lines changed: 0 additions & 12 deletions
This file was deleted.

pytest_rts/plugin.py

Lines changed: 34 additions & 80 deletions
Original file line numberDiff line numberDiff line change
@@ -1,44 +1,35 @@
11
"""Code for pytest-rts plugin logic"""
22
import logging
33
import os
4-
import sqlite3
54

65
import pytest
76

87
from pytest_rts.pytest.init_phase_plugin import InitPhasePlugin
9-
from pytest_rts.pytest.normal_phase_plugin import NormalPhasePlugin
10-
from pytest_rts.pytest.update_phase_plugin import UpdatePhasePlugin
8+
from pytest_rts.pytest.run_phase_plugin import RunPhasePlugin
9+
from pytest_rts.utils.common import (
10+
DB_FILE_PREFIX,
11+
get_coverage_file_filename,
12+
get_existing_tests,
13+
get_tests_committed,
14+
get_tests_current,
15+
)
1116
from pytest_rts.utils.git import (
1217
get_current_head_hash,
1318
is_git_repo,
1419
repo_has_commits,
1520
)
16-
from pytest_rts.utils.selection import (
17-
get_tests_and_data_committed,
18-
get_tests_and_data_current,
19-
)
20-
from pytest_rts.utils.mappinghelper import MappingHelper
21-
from pytest_rts.utils.testgetter import TestGetter
22-
23-
DB_FILE_NAME = "mapping.db"
24-
25-
26-
class MappingConn: # pylint: disable=too-few-public-methods
27-
"""Mapping connection"""
28-
29-
_conn = None
30-
31-
@classmethod
32-
def conn(cls):
33-
"""SQLite connection"""
34-
if not cls._conn:
35-
cls._conn = sqlite3.connect(DB_FILE_NAME)
36-
return cls._conn
3721

3822

3923
def pytest_addoption(parser):
4024
"""Register pytest flags"""
41-
parser.addoption("--rts", action="store_true", default=False, help="run rts")
25+
group = parser.getgroup("pytest-rts")
26+
group.addoption("--rts", action="store_true", default=False, help="run rts")
27+
group.addoption(
28+
"--committed",
29+
action="store_true",
30+
default=False,
31+
help="Check committed changes",
32+
)
4233

4334

4435
def pytest_configure(config):
@@ -61,76 +52,39 @@ def pytest_configure(config):
6152
)
6253
return
6354

64-
init_required = not os.path.isfile(DB_FILE_NAME)
65-
66-
mapping_helper = MappingHelper(MappingConn.conn())
67-
test_getter = TestGetter(MappingConn.conn())
55+
init_required = not os.path.isfile(get_coverage_file_filename())
6856

6957
if init_required:
7058
logger.info("No mapping database detected, starting initialization...")
71-
config.pluginmanager.register(
72-
InitPhasePlugin(mapping_helper), "rts-init-plugin"
73-
)
59+
config.pluginmanager.register(InitPhasePlugin(), "rts-init-plugin")
7460
return
7561

76-
workdir_data = get_tests_and_data_current(mapping_helper, test_getter)
77-
78-
logger.info("WORKING DIRECTORY CHANGES")
79-
logger.info("Found %s changed test files", workdir_data.changed_testfiles_amount)
80-
logger.info("Found %s changed src files", workdir_data.changed_srcfiles_amount)
81-
logger.info("Found %s tests to execute\n", len(workdir_data.test_set))
62+
workdir_changes = not config.option.committed
63+
existing_tests = get_existing_tests()
8264

83-
if workdir_data.test_set:
84-
logger.info(
85-
"Running WORKING DIRECTORY test set and exiting without updating..."
86-
)
65+
if workdir_changes:
66+
logger.info("Checking working directory changes.")
67+
workdir_tests = get_tests_current()
8768
config.pluginmanager.register(
88-
NormalPhasePlugin(workdir_data.test_set, test_getter)
69+
RunPhasePlugin(workdir_tests, existing_tests), "rts-workdir-plugin"
8970
)
9071
return
9172

92-
logger.info("No WORKING DIRECTORY tests to run, checking COMMITTED changes...")
93-
94-
current_hash = get_current_head_hash()
95-
previous_hash = mapping_helper.last_update_hash
96-
if current_hash == previous_hash:
97-
pytest.exit("Database is updated to the current commit state", 0)
73+
logger.info("Checking committed changes.")
74+
previous_hash = get_coverage_file_filename().split(".")[1]
75+
if previous_hash == get_current_head_hash():
76+
pytest.exit(0, "Database was initialized at this commit. No changes detected.")
9877

99-
logger.info("Comparison: %s\n", " => ".join([current_hash, previous_hash]))
78+
committed_tests = get_tests_committed(previous_hash)
10079

101-
committed_data = get_tests_and_data_committed(mapping_helper, test_getter)
102-
103-
logger.info("COMMITTED CHANGES")
104-
logger.info("Found %s changed test files", committed_data.changed_testfiles_amount)
105-
logger.info("Found %s changed src files", committed_data.changed_srcfiles_amount)
106-
logger.info(
107-
"Found %s newly added tests",
108-
committed_data.new_tests_amount,
80+
config.pluginmanager.register(
81+
RunPhasePlugin(committed_tests, existing_tests), "rts-committed-plugin"
10982
)
110-
logger.info("Found %s tests to execute\n", len(committed_data.test_set))
111-
112-
if committed_data.warning_needed:
113-
logger.info(
114-
"WARNING: New lines were added to the following files but no new tests discovered:"
115-
)
116-
logger.info("\n".join(committed_data.files_to_warn))
117-
118-
logger.info("=> Executing tests (if any) and updating database")
119-
mapping_helper.set_last_update_hash(current_hash)
120-
121-
mapping_helper.update_mapping(committed_data.update_data)
122-
123-
if committed_data.test_set:
124-
config.pluginmanager.register(
125-
UpdatePhasePlugin(committed_data.test_set, mapping_helper, test_getter)
126-
)
127-
return
128-
129-
pytest.exit("No tests to run", 0)
83+
return
13084

13185

13286
def pytest_unconfigure(config):
13387
"""Cleanup after pytest run"""
13488
if config.option.rts:
135-
MappingConn.conn().commit()
136-
MappingConn.conn().close()
89+
if config.pluginmanager.hasplugin("rts-init-plugin"):
90+
os.rename(".coverage", f"{DB_FILE_PREFIX}.{get_current_head_hash()}")

pytest_rts/pytest/collect_plugin.py

Lines changed: 0 additions & 27 deletions
This file was deleted.
Lines changed: 14 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,28 +1,19 @@
1-
"""This module contains code for initializing the mapping database"""
2-
import os
1+
"""This module contains code for the first run of pytest-rts"""
32

4-
import coverage
53

6-
from pytest_rts.pytest.mapper_plugin import MapperPlugin
7-
from pytest_rts.utils.common import calculate_func_lines
8-
from pytest_rts.utils.git import get_current_head_hash
9-
10-
11-
class InitPhasePlugin(MapperPlugin):
4+
class InitPhasePlugin:
125
"""Class to handle mapping database initialization"""
136

14-
def __init__(self, mappinghelper):
15-
""""Constructor calls database and Coverage.py initialization"""
16-
super().__init__(mappinghelper)
17-
self.mappinghelper.set_last_update_hash(get_current_head_hash())
7+
def __init__(self):
8+
""""Coverage.py object placeholder set to None"""
9+
self.cov = None
10+
11+
def pytest_collection_modifyitems(
12+
self, session, config, items
13+
): # pylint: disable=unused-argument
14+
"""Set the Coverage object from pytest-cov"""
15+
self.cov = config.pluginmanager.getplugin("_cov").cov_controller.cov
1816

19-
def pytest_collection_modifyitems(self, session, config, items):
20-
"""Calculate function start and end line numbers from testfiles"""
21-
del session, config
22-
self.testfiles = {os.path.relpath(item.location[0]) for item in items}
23-
self.test_func_lines = {
24-
testfile_path: calculate_func_lines(
25-
coverage.python.get_python_source(testfile_path)
26-
)
27-
for testfile_path in self.testfiles
28-
}
17+
def pytest_runtest_logstart(self, nodeid, location):
18+
"""Switch test function name in Coverage.py when a test starts running"""
19+
self.cov.switch_context(nodeid)

pytest_rts/pytest/mapper_plugin.py

Lines changed: 0 additions & 46 deletions
This file was deleted.

pytest_rts/pytest/normal_phase_plugin.py

Lines changed: 0 additions & 25 deletions
This file was deleted.
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
"""This module contains code for running a specific test set"""
2+
# pylint: disable=too-few-public-methods
3+
from pytest_rts.pytest.fake_item import FakeItem
4+
from pytest_rts.utils.common import filter_and_sort_pytest_items
5+
6+
7+
class RunPhasePlugin:
8+
"""Plugin class for pytest"""
9+
10+
def __init__(self, selected_test_set, existing_tests):
11+
"""Set Coverage.py object placeholder to None"""
12+
self.cov = None
13+
self.selected_test_set = selected_test_set
14+
self.existing_tests = existing_tests
15+
16+
def pytest_collection_modifyitems(self, session, config, items):
17+
"""Select only specific tests for running"""
18+
self.cov = config.pluginmanager.getplugin("_cov").cov_controller.cov
19+
original_length = len(items)
20+
items[:] = filter_and_sort_pytest_items(
21+
self.selected_test_set, items, self.existing_tests
22+
)
23+
session.config.hook.pytest_deselected(
24+
items=([FakeItem(session.config)] * (original_length - len(items)))
25+
)
26+
27+
def pytest_runtest_logstart(self, nodeid, location):
28+
"""Switch test function name in Coverage.py when a test starts running"""
29+
self.cov.switch_context(nodeid)

pytest_rts/pytest/update_phase_plugin.py

Lines changed: 0 additions & 50 deletions
This file was deleted.

0 commit comments

Comments
 (0)