Repository: WithSecureOpenSource/pytest-rts (language: python)

Issue:
pytest-cov integration: execution of new tests
As agreed let's integrate with pytest-cov and move with **small steps with a limited scope** of PRs to do reviews faster. @guotin three "features" were suggested before:

1. all the new tests (both committed and uncommitted)
2. all the changed tests (both committed and uncommitted)
3. all tests that are related to the changed source lines

And as you said, from pytest-cov pp. 2 and 3 are the same. Let's select the simplest functionality that we can build fast. For example, it could be part of p 1.: running all uncommitted tests. How does it sound? Do you see any simpler functionality?

I suppose we need a snapshot(copy) of coverage database to find tests that are not listed there thus, root folder will contain `.coverage.[COMMIT_HASH]` (any name could be used) file and a flag `--rts-coverage-db=.coverage.[COMMIT_HASH]` will be passed.

From the technical point of view let's:
* In very first commit add `__version__ = "2.0.0"` in `pytest-rts/__init__.py`
* Remove all irrelevant code and tests - we can always bring it back from history. I think we don't need git module for discovering new tests as pytest, in theory, will pass us test items and we can check if we see them in the DB snapshot. Do I understand the process right? DB utils integration not needed here as well as we are using pytest-cov API, isn't it?


Discussion / hints:

Fix patch:
diff --git a/README.md b/README.md
index c8146ba..aeb8697 100644
--- a/README.md
+++ b/README.md
@@ -26,15 +26,12 @@ More detailed usage is described in the [tutorial][tutorial]
    - install `pytest-rts`
 3. Switch to directory with target project
 4. Install all the dependencies needed for testing (should be installed into the same pytest-rts virtual environment)
-5. Execute `pytest --rts` which will run the entire test suite and build a mapping database
+5. Execute `pytest --cov=<path to code> --cov-context=test` which will run the entire test suite and build a mapping database with [pytest-cov](https://github.com/pytest-dev/pytest-cov)
+6. Rename the coverage file produced by `pytest-cov` to your liking. Example: `mv .coverage pytest-rts-coverage`
 
-#### Running tests related to the changes
+#### Running new tests
 
-1. execute `pytest --rts` after doing changes
-
-#### Running evaluation code
-
-1. execute `pytest_rts_eval` in target project directory
+1. execute `pytest --rts --rts-coverage-db=<your coverage file>` after adding new tests
 
 ## <a name="dev"></a> Development
 
diff --git a/setup.py b/setup.py
index eb153b8..07500f1 100644
--- a/setup.py
+++ b/setup.py
@@ -18,7 +18,6 @@ def _read_long_description():
     .replace("v", "", 1)
 )
 DEV_REQUIRE = [
-    "pytest-cov",
     "pytest-socket",
     "tox",
     "python-semantic-release",
@@ -45,16 +44,11 @@ def _read_long_description():
     version=GIT_VERSION,
     packages=find_packages(exclude=[f"{NAME}.tests", f"{NAME}.tests.*"]),
     entry_points={
-        "console_scripts": [
-            f"{NAME}_eval={NAME}.tests.evaluation.start:main",
-            f"{NAME}_capture_exitcode={NAME}.tests.evaluation.exitcode:main",
-            f"{NAME}_collect={NAME}.collect:main",
-        ],
         "pytest11": [
             f"{NAME_DASHED}={NAME}.plugin",
         ],
     },
-    install_requires=["pydriller", "coverage", "pytest"],
+    install_requires=["coverage", "pytest", "pytest-cov"],
     extras_require={"dev": DEV_REQUIRE},
     classifiers=[
         "Programming Language :: Python",
diff --git a/tox.ini b/tox.ini
index 8a10f0b..b098f22 100644
--- a/tox.ini
+++ b/tox.ini
@@ -4,14 +4,17 @@ skipsdist = True
 envlist = py36,py37,py38,py39
 
 [testenv]
-deps = .[dev]
+setenv =
+    PYTHONPATH = {toxinidir}
 commands =
         python -m pip install --upgrade pip
+        python -m pip install .[dev]
         pylint -j 0 -s n setup.py pytest_rts
         mypy setup.py pytest_rts --ignore-missing-imports
         safety check
         pytest \
           --cov=pytest_rts \
+          --cov-fail-under=96 \
           --cov-report html \
           --cov-report term \
           --disable-socket \


Test patch:
diff --git a/pytest.ini b/pytest.ini
index b69b1cf..c14dca6 100644
--- a/pytest.ini
+++ b/pytest.ini
@@ -1,3 +1,4 @@
 [pytest]
-# Prevent helper project tests being collected as tests for pytest-rts
+pytester_example_dir = ./pytest_rts/tests/helper_project
+addopts = -p pytester
 norecursedirs = pytest_rts/tests/helper_project
diff --git a/pytest_rts/__init__.py b/pytest_rts/__init__.py
index bc65031..386858c 100644
--- a/pytest_rts/__init__.py
+++ b/pytest_rts/__init__.py
@@ -1,2 +1,2 @@
 """pytest-rts: avoid already imported warning: PYTEST_DONT_REWRITE"""
-__version__ = "1.2.1"
+__version__ = "2.0.0"
diff --git a/pytest_rts/collect.py b/pytest_rts/collect.py
deleted file mode 100644
index 9d50c99..0000000
--- a/pytest_rts/collect.py
+++ /dev/null
@@ -1,12 +0,0 @@
-"""This module contains code for collecting newly added tests from pytest"""
-import pytest
-from pytest_rts.pytest.collect_plugin import CollectPlugin
-
-
-def main():
-    """Collect newly added tests and store them to database with pytest --collect-only"""
-    pytest.main(["--collect-only", "-p", "no:terminal"], plugins=[CollectPlugin()])
-
-
-if __name__ == "__main__":
-    main()
diff --git a/pytest_rts/plugin.py b/pytest_rts/plugin.py
index cbcd6ca..ab3f2db 100644
--- a/pytest_rts/plugin.py
+++ b/pytest_rts/plugin.py
@@ -1,136 +1,36 @@
 """Code for pytest-rts plugin logic"""
-import logging
 import os
-import sqlite3
 
 import pytest
+from _pytest.config import Config
+from _pytest.config.argparsing import Parser
 
-from pytest_rts.pytest.init_phase_plugin import InitPhasePlugin
-from pytest_rts.pytest.normal_phase_plugin import NormalPhasePlugin
-from pytest_rts.pytest.update_phase_plugin import UpdatePhasePlugin
-from pytest_rts.utils.git import (
-    get_current_head_hash,
-    is_git_repo,
-    repo_has_commits,
-)
-from pytest_rts.utils.selection import (
-    get_tests_and_data_committed,
-    get_tests_and_data_current,
-)
-from pytest_rts.utils.mappinghelper import MappingHelper
-from pytest_rts.utils.testgetter import TestGetter
+from pytest_rts.pytest.runner_plugin import RunnerPlugin
+from pytest_rts.utils.common import get_existing_tests
 
-DB_FILE_NAME = "mapping.db"
 
-
-class MappingConn:  # pylint: disable=too-few-public-methods
-    """Mapping connection"""
-
-    _conn = None
-
-    @classmethod
-    def conn(cls):
-        """SQLite connection"""
-        if not cls._conn:
-            cls._conn = sqlite3.connect(DB_FILE_NAME)
-        return cls._conn
-
-
-def pytest_addoption(parser):
+def pytest_addoption(parser: Parser) -> None:
     """Register pytest flags"""
-    parser.addoption("--rts", action="store_true", default=False, help="run rts")
+    group = parser.getgroup("pytest-rts")
+    group.addoption("--rts", action="store_true", default=False, help="Run pytest-rts")
+    group.addoption(
+        "--rts-coverage-db",
+        action="store",
+        default="",
+        help="Coverage file pytest-rts",
+    )
 
 
-def pytest_configure(config):
+def pytest_configure(config: Config) -> None:
     """Register RTS plugins based on state"""
-    logger = logging.getLogger()
-    logging.basicConfig(format="%(message)s", level=logging.INFO)
-
     if not config.option.rts:
         return
 
-    if not is_git_repo():
-        logger.info(
-            "Not a git repository! pytest-rts is disabled. Run git init before using pytest-rts."
-        )
-        return
-
-    if not repo_has_commits():
-        logger.info(
-            "No commits yet! pytest-rts is disabled. Create a git commit before using pytest-rts."
-        )
-        return
-
-    init_required = not os.path.isfile(DB_FILE_NAME)
-
-    mapping_helper = MappingHelper(MappingConn.conn())
-    test_getter = TestGetter(MappingConn.conn())
-
-    if init_required:
-        logger.info("No mapping database detected, starting initialization...")
-        config.pluginmanager.register(
-            InitPhasePlugin(mapping_helper), "rts-init-plugin"
-        )
-        return
-
-    workdir_data = get_tests_and_data_current(mapping_helper, test_getter)
-
-    logger.info("WORKING DIRECTORY CHANGES")
-    logger.info("Found %s changed test files", workdir_data.changed_testfiles_amount)
-    logger.info("Found %s changed src files", workdir_data.changed_srcfiles_amount)
-    logger.info("Found %s tests to execute\n", len(workdir_data.test_set))
-
-    if workdir_data.test_set:
-        logger.info(
-            "Running WORKING DIRECTORY test set and exiting without updating..."
-        )
-        config.pluginmanager.register(
-            NormalPhasePlugin(workdir_data.test_set, test_getter)
-        )
-        return
-
-    logger.info("No WORKING DIRECTORY tests to run, checking COMMITTED changes...")
-
-    current_hash = get_current_head_hash()
-    previous_hash = mapping_helper.last_update_hash
-    if current_hash == previous_hash:
-        pytest.exit("Database is updated to the current commit state", 0)
-
-    logger.info("Comparison: %s\n", " => ".join([current_hash, previous_hash]))
-
-    committed_data = get_tests_and_data_committed(mapping_helper, test_getter)
-
-    logger.info("COMMITTED CHANGES")
-    logger.info("Found %s changed test files", committed_data.changed_testfiles_amount)
-    logger.info("Found %s changed src files", committed_data.changed_srcfiles_amount)
-    logger.info(
-        "Found %s newly added tests",
-        committed_data.new_tests_amount,
-    )
-    logger.info("Found %s tests to execute\n", len(committed_data.test_set))
-
-    if committed_data.warning_needed:
-        logger.info(
-            "WARNING: New lines were added to the following files but no new tests discovered:"
-        )
-        logger.info("\n".join(committed_data.files_to_warn))
-
-    logger.info("=> Executing tests (if any) and updating database")
-    mapping_helper.set_last_update_hash(current_hash)
-
-    mapping_helper.update_mapping(committed_data.update_data)
-
-    if committed_data.test_set:
-        config.pluginmanager.register(
-            UpdatePhasePlugin(committed_data.test_set, mapping_helper, test_getter)
-        )
-        return
-
-    pytest.exit("No tests to run", 0)
+    if not config.option.rts_coverage_db:
+        pytest.exit("No coverage file provided", 2)
 
+    if not os.path.exists(config.option.rts_coverage_db):
+        pytest.exit("Provided coverage file does not exist", 2)
 
-def pytest_unconfigure(config):
-    """Cleanup after pytest run"""
-    if config.option.rts:
-        MappingConn.conn().commit()
-        MappingConn.conn().close()
+    existing_tests = get_existing_tests(config.option.rts_coverage_db)
+    config.pluginmanager.register(RunnerPlugin(existing_tests))
diff --git a/pytest_rts/pytest/collect_plugin.py b/pytest_rts/pytest/collect_plugin.py
deleted file mode 100644
index e154589..0000000
--- a/pytest_rts/pytest/collect_plugin.py
+++ /dev/null
@@ -1,27 +0,0 @@
-"""This module contains code for collecting newly added tests"""
-# pylint: disable=too-few-public-methods
-import sqlite3
-from pytest_rts.plugin import DB_FILE_NAME
-from pytest_rts.utils.testgetter import TestGetter
-
-
-class CollectPlugin:
-    """Plugin class for pytest to collect newly added tests"""
-
-    def __init__(self):
-        """Query existing test functions from database before collection"""
-        self.collected = set()
-        self.conn = sqlite3.connect(DB_FILE_NAME)
-        self.testgetter = TestGetter(self.conn)
-        self.existing_tests = self.testgetter.existing_tests
-        self.testgetter.delete_newly_added_tests()
-
-    def pytest_collection_modifyitems(self, session, config, items):
-        """Select tests that have not been previously seen"""
-        del session, config
-        for item in items:
-            if item.nodeid not in self.existing_tests:
-                self.collected.add(item.nodeid)
-        self.testgetter.set_newly_added_tests(self.collected)
-        self.conn.commit()
-        self.conn.close()
diff --git a/pytest_rts/pytest/fake_item.py b/pytest_rts/pytest/fake_item.py
index 0333d00..c40369a 100644
--- a/pytest_rts/pytest/fake_item.py
+++ b/pytest_rts/pytest/fake_item.py
@@ -1,8 +1,9 @@
 """This module contains a fake pytest item class"""
+from _pytest.config import Config
 
 
 class FakeItem:  # pylint: disable=too-few-public-methods
     """Fake class"""
 
-    def __init__(self, config):
+    def __init__(self, config: Config) -> None:
         self.config = config
diff --git a/pytest_rts/pytest/init_phase_plugin.py b/pytest_rts/pytest/init_phase_plugin.py
deleted file mode 100644
index ba2db03..0000000
--- a/pytest_rts/pytest/init_phase_plugin.py
+++ /dev/null
@@ -1,28 +0,0 @@
-"""This module contains code for initializing the mapping database"""
-import os
-
-import coverage
-
-from pytest_rts.pytest.mapper_plugin import MapperPlugin
-from pytest_rts.utils.common import calculate_func_lines
-from pytest_rts.utils.git import get_current_head_hash
-
-
-class InitPhasePlugin(MapperPlugin):
-    """Class to handle mapping database initialization"""
-
-    def __init__(self, mappinghelper):
-        """"Constructor calls database and Coverage.py initialization"""
-        super().__init__(mappinghelper)
-        self.mappinghelper.set_last_update_hash(get_current_head_hash())
-
-    def pytest_collection_modifyitems(self, session, config, items):
-        """Calculate function start and end line numbers from testfiles"""
-        del session, config
-        self.testfiles = {os.path.relpath(item.location[0]) for item in items}
-        self.test_func_lines = {
-            testfile_path: calculate_func_lines(
-                coverage.python.get_python_source(testfile_path)
-            )
-            for testfile_path in self.testfiles
-        }
diff --git a/pytest_rts/pytest/mapper_plugin.py b/pytest_rts/pytest/mapper_plugin.py
deleted file mode 100644
index 1c28570..0000000
--- a/pytest_rts/pytest/mapper_plugin.py
+++ /dev/null
@@ -1,46 +0,0 @@
-"""This module contains code for initializing the mapping database"""
-# pylint: disable=too-few-public-methods
-from timeit import default_timer as timer
-
-import coverage
-import pytest
-from _pytest.python import Function
-
-from pytest_rts.utils.mappinghelper import TestrunData
-
-
-class MapperPlugin:
-    """Class to handle mapping database initialization"""
-
-    def __init__(self, mappinghelper):
-        """"Constructor calls database and Coverage.py initialization"""
-        self.cov = coverage.Coverage(data_file=None)
-        self.cov._warn_unimported_source = False
-        self.mappinghelper = mappinghelper
-        self.mappinghelper.init_mapping()
-        self.testfiles = {testfile[1] for testfile in self.mappinghelper.testfiles}
-        self.test_func_lines = None
-
-    @pytest.hookimpl(hookwrapper=True)
-    def pytest_runtest_protocol(self, item, nextitem):
-        """Start coverage collection for each test function run and save data"""
-        del nextitem
-        if isinstance(item, Function):
-            start = timer()
-            self.cov.erase()
-            self.cov.start()
-            yield
-            self.cov.stop()
-            end = timer()
-            elapsed = round(end - start, 4)
-
-            testrun_data = TestrunData(
-                pytest_item=item,
-                elapsed_time=elapsed,
-                coverage_data=self.cov.get_data(),
-                found_testfiles=self.testfiles,
-                test_function_lines=self.test_func_lines,
-            )
-            self.mappinghelper.save_testrun_data(testrun_data)
-        else:
-            yield
diff --git a/pytest_rts/pytest/normal_phase_plugin.py b/pytest_rts/pytest/normal_phase_plugin.py
deleted file mode 100644
index 3c9844b..0000000
--- a/pytest_rts/pytest/normal_phase_plugin.py
+++ /dev/null
@@ -1,25 +0,0 @@
-"""This module contains code for running a specific test set without mapping database updating"""
-# pylint: disable=too-few-public-methods
-from pytest_rts.pytest.fake_item import FakeItem
-from pytest_rts.utils.common import filter_and_sort_pytest_items
-
-
-class NormalPhasePlugin:
-    """Plugin class for pytest"""
-
-    def __init__(self, test_set, testgetter):
-        """Initialize database connection"""
-        self.test_set = test_set
-        self.testgetter = testgetter
-        self.test_func_times = self.testgetter.test_function_runtimes
-
-    def pytest_collection_modifyitems(self, session, config, items):
-        """Select only specific tests for running and prioritize them based on queried times"""
-        del config
-        original_length = len(items)
-        items[:] = filter_and_sort_pytest_items(
-            self.test_set, items, self.test_func_times
-        )
-        session.config.hook.pytest_deselected(
-            items=([FakeItem(session.config)] * (original_length - len(items)))
-        )
diff --git a/pytest_rts/pytest/runner_plugin.py b/pytest_rts/pytest/runner_plugin.py
new file mode 100644
index 0000000..a5b3650
--- /dev/null
+++ b/pytest_rts/pytest/runner_plugin.py
@@ -0,0 +1,30 @@
+"""This module contains code for running a specific test set"""
+# pylint: disable=too-few-public-methods
+from typing import List, Set
+
+from _pytest.main import Session
+from _pytest.nodes import Item
+
+from pytest_rts.pytest.fake_item import FakeItem
+from pytest_rts.utils.common import filter_pytest_items
+
+
+class RunnerPlugin:
+    """Plugin class for pytest"""
+
+    def __init__(self, existing_tests: Set[str]) -> None:
+        """Set existing tests"""
+        self.existing_tests = existing_tests
+
+    def pytest_collection_modifyitems(
+        self,
+        session: Session,
+        config,  # pylint: disable=unused-argument
+        items: List[Item],
+    ) -> None:
+        """Select only specific tests for running"""
+        original_length = len(items)
+        items[:] = filter_pytest_items(items, self.existing_tests)
+        session.config.hook.pytest_deselected(
+            items=([FakeItem(session.config)] * (original_length - len(items)))
+        )
diff --git a/pytest_rts/pytest/update_phase_plugin.py b/pytest_rts/pytest/update_phase_plugin.py
deleted file mode 100644
index 679149a..0000000
--- a/pytest_rts/pytest/update_phase_plugin.py
+++ /dev/null
@@ -1,50 +0,0 @@
-"""This module contains code for running a specific test set with mapping database updating"""
-import os
-
-import coverage
-
-from pytest_rts.pytest.fake_item import FakeItem
-from pytest_rts.utils.common import calculate_func_lines, filter_and_sort_pytest_items
-from pytest_rts.pytest.mapper_plugin import MapperPlugin
-
-
-def _read_testfile_functions(testfile_path):
-    """Calculate test file function lines and
-    expect an error for deleted test file between commits
-    """
-    try:
-        return calculate_func_lines(coverage.python.get_python_source(testfile_path))
-    except coverage.misc.NoSource:
-        return {}
-
-
-class UpdatePhasePlugin(MapperPlugin):
-    """Class to handle running of selected tests and updating mapping with the results"""
-
-    def __init__(self, test_set, mappinghelper, testgetter):
-        """Constructor opens database connection and initializes Coverage.py"""
-        super().__init__(mappinghelper)
-        self.test_set = test_set
-        self.testgetter = testgetter
-        self.test_func_times = self.testgetter.test_function_runtimes
-
-    def pytest_collection_modifyitems(self, session, config, items):
-        """
-        Sorts tests based on database duration and
-        calculates test function start and end line numbers
-        """
-        del config
-        original_length = len(items)
-        items[:] = filter_and_sort_pytest_items(
-            self.test_set, items, self.test_func_times
-        )
-
-        self.testfiles.update({os.path.relpath(item.location[0]) for item in items})
-        self.test_func_lines = {
-            testfile_path: _read_testfile_functions(testfile_path)
-            for testfile_path in self.testfiles
-        }
-
-        session.config.hook.pytest_deselected(
-            items=([FakeItem(session.config)] * (original_length - len(items)))
-        )
diff --git a/pytest_rts/tests/evaluation/__init__.py b/pytest_rts/tests/__init__.py
similarity index 100%
rename from pytest_rts/tests/evaluation/__init__.py
rename to pytest_rts/tests/__init__.py
diff --git a/pytest_rts/tests/conftest.py b/pytest_rts/tests/conftest.py
deleted file mode 100644
index fe9cf84..0000000
--- a/pytest_rts/tests/conftest.py
+++ /dev/null
@@ -1,45 +0,0 @@
-"""This module contains temporary Git repository initialization and teardown for tests"""
-import os
-import subprocess
-import shutil
-import pytest
-from pytest_rts.plugin import DB_FILE_NAME
-from testhelper import TestHelper
-
-
-@pytest.fixture(scope="session", autouse=True)
-def temp_project_repo(tmpdir_factory):
-    """Create a temporary Git repository and initialize the tool there"""
-    temp_folder = tmpdir_factory.mktemp("temp").join("testrepo")
-    shutil.copytree("./pytest_rts/tests/helper_project", temp_folder)
-    os.chdir(temp_folder)
-
-    with open(".gitignore", "w") as gitignore:
-        lines = ["*.db\n", ".coverage\n", "*__pycache__*\n"]
-        for line in lines:
-            gitignore.write(line)
-
-    subprocess.run(["git", "init"], check=True)
-    subprocess.run(["git", "config", "user.name", "pytest"], check=True)
-    subprocess.run(["git", "config", "user.email", "pytest@example.com"], check=True)
-    subprocess.run(["git", "add", "."], check=True)
-    subprocess.run(["git", "commit", "-m", "1"], check=True)
-    subprocess.run(["pytest", "--rts"], check=True)
-    return temp_folder
-
-
-@pytest.fixture(scope="function", autouse=True)
-def teardown_method():
-    """Reset state of temporary git repository"""
-    yield
-    subprocess.run(["git", "restore", "."], check=True)
-    subprocess.run(["git", "checkout", "master"], check=True)
-    subprocess.run(["git", "branch", "-D", "new-branch"], check=False)
-    os.remove(DB_FILE_NAME)
-    subprocess.run(["pytest", "--rts"], check=True)
-
-
-@pytest.fixture
-def helper():
-    """TestHelper as a fixture for tests"""
-    return TestHelper()
diff --git a/pytest_rts/tests/evaluation/capture_specific_plugin.py b/pytest_rts/tests/evaluation/capture_specific_plugin.py
deleted file mode 100644
index 2886206..0000000
--- a/pytest_rts/tests/evaluation/capture_specific_plugin.py
+++ /dev/null
@@ -1,18 +0,0 @@
-"""This module contains code for capturing pytest exit code for running a test set"""
-
-
-class CaptureSpecificPlugin:  # pylint: disable=too-few-public-methods
-    """Plugin class for pytest"""
-
-    def __init__(self, test_set):
-        """Set test set as a value"""
-        self.test_set = test_set
-
-    def pytest_collection_modifyitems(self, session, config, items):
-        """Only select specific tests for running"""
-        del session, config
-        selected = []
-        for item in items:
-            if item.nodeid in self.test_set:
-                selected.append(item)
-        items[:] = selected
diff --git a/pytest_rts/tests/evaluation/evaluation_utils.py b/pytest_rts/tests/evaluation/evaluation_utils.py
deleted file mode 100644
index 700c947..0000000
--- a/pytest_rts/tests/evaluation/evaluation_utils.py
+++ /dev/null
@@ -1,169 +0,0 @@
-"""Helper functions for evaluation code"""
-from functools import wraps
-import logging
-import random
-import sqlite3
-import subprocess
-from typing import List, Set
-
-from pytest_rts.plugin import DB_FILE_NAME
-from pytest_rts.utils.git import (
-    get_git_repo,
-    get_current_head_hash,
-    changed_files_between_commits,
-)
-
-
-def with_connection(func):
-    @wraps(func)
-    def wrapper(*args, **kwargs):
-        conn = sqlite3.connect(DB_FILE_NAME)
-        try:
-            return func(*args, **kwargs, conn=conn)
-        finally:
-            conn.close()
-
-    return wrapper
-
-
-def full_diff_between_commits(commit1, commit2) -> str:
-    """Git diff between commits"""
-    repo = get_git_repo(None).repo.git
-    return repo.diff(commit1, commit2)
-
-
-def select_random_file(files) -> str:
-    """Select a random source file from list"""
-    return random.choice(files)
-
-
-def delete_random_line(filepath):
-    """Replace a random line containing code to a newline"""
-    try:
-        with open(filepath, "r") as randomfile:
-            data = randomfile.readlines()
-            while True:
-                rand_line = random.randint(0, len(data) - 1)
-                if data[rand_line] != "\n":
-                    break
-            data[rand_line] = "\n"  # replace random line with newline.
-
-        with open(filepath, "w") as randomfile:
-            for line in data:
-                randomfile.write(line)
-
-    except FileNotFoundError:
-        logging.getLogger().error(f"can't open selected random file {filepath}")
-        exit(1)
-
-
-def capture_specific_exit_code(tests, max_wait) -> int:
-    """Run pytest with a given test set and capture exit code"""
-    try:
-        specific_exit_code = subprocess.run(
-            ["pytest_rts_capture_exitcode"] + tests,
-            timeout=max_wait,
-            stderr=subprocess.DEVNULL,
-            stdout=subprocess.DEVNULL,
-            check=False,
-        ).returncode
-    except subprocess.TimeoutExpired:
-        specific_exit_code = -1
-
-    return specific_exit_code
-
-
-def capture_all_exit_code(max_wait) -> int:
-    """Run entire pytest test suite and capture exit code"""
-    try:
-        all_exit_code = subprocess.run(
-            ["pytest", "-p", "no:terminal"],
-            timeout=max_wait,
-            stderr=subprocess.DEVNULL,
-            stdout=subprocess.DEVNULL,
-            check=False,
-        ).returncode
-    except subprocess.TimeoutExpired:
-        all_exit_code = -1
-
-    return all_exit_code
-
-
-def print_remove_test_output(
-    i,
-    project_name,
-    commithash,
-    deletes,
-    full_test_suite_size,
-    line_test_suite_size,
-    file_test_suite_size,
-    exitcode_line,
-    exitcode_file,
-    exitcode_all,
-    db_name,
-    logger,
-):
-    """Print random remove test statistics"""
-    logger.info("============")
-    logger.info(f"iteration: {i+1}")
-    logger.info(f"project name: {project_name}")
-    logger.info(f"commit hash: {commithash}")
-    logger.info(f"removed {deletes} random src file lines")
-    logger.info(f"size of full test suite: {full_test_suite_size}")
-    logger.info(f"size of line level test suite: {line_test_suite_size}")
-    logger.info(f"size of file level test suite: {file_test_suite_size}")
-    logger.info(
-        f"exitcodes: line-level: {exitcode_line}, file-level: {exitcode_file}, all: {exitcode_all}"
-    )
-    logger.info(f"STORING TO DATABASE: {db_name}")
-    logger.info("============")
-
-
-@with_connection
-def get_test_suite_size(conn=None) -> int:
-    """Query how many tests are in mapping database"""
-    return int(conn.execute("SELECT count() FROM test_function").fetchone()[0])
-
-
-@with_connection
-def get_all_tests_for_srcfile(file_id, conn=None) -> List[str]:
-    """Query all tests for a source code file"""
-    return [
-        line[0]
-        for line in conn.execute(
-            """ SELECT DISTINCT context
-                FROM test_function
-                JOIN test_map ON test_function.id == test_map.test_function_id
-                WHERE test_map.file_id = ? """,
-            (file_id,),
-        )
-    ]
-
-
-@with_connection
-def get_srcfile_id(path, conn=None) -> int:
-    """Get the id in the mapping database for a source code file"""
-    return conn.execute("SELECT id FROM src_file WHERE path == ?", (path,)).fetchone()[
-        0
-    ]
-
-
-def get_file_level_tests_between_commits(commit1, commit2) -> Set[str]:
-    """Get the file-level granularity test set between git commits"""
-    return {
-        test
-        for path in changed_files_between_commits(commit1, commit2)
-        for test in get_all_tests_for_srcfile(get_srcfile_id(path))
-    }
-
-
-@with_connection
-def get_mapping_srcfiles(conn=None) -> List[str]:
-    """Get all the tool's covered source code files"""
-    return [x[0] for x in conn.execute("SELECT path FROM src_file")]
-
-
-@with_connection
-def get_mapping_init_hash(conn=None) -> str:
-    """Get the git commit hash for initial state of the mapping database"""
-    return conn.execute("SELECT hash FROM last_update_hash").fetchone()[0]
diff --git a/pytest_rts/tests/evaluation/exitcode.py b/pytest_rts/tests/evaluation/exitcode.py
deleted file mode 100644
index 7f272e3..0000000
--- a/pytest_rts/tests/evaluation/exitcode.py
+++ /dev/null
@@ -1,16 +0,0 @@
-"""This module contains code to capture pytest exitcode for the given test set"""
-import sys
-import pytest
-from pytest_rts.tests.evaluation.capture_specific_plugin import CaptureSpecificPlugin
-
-
-def main():
-    test_set = set(sys.argv[1:])
-    exit_code = pytest.main(
-        ["-p", "no:terminal"], plugins=[CaptureSpecificPlugin(test_set)]
-    )
-    exit(int(exit_code))
-
-
-if __name__ == "__main__":
-    main()
diff --git a/pytest_rts/tests/evaluation/results_db.py b/pytest_rts/tests/evaluation/results_db.py
deleted file mode 100644
index ac11a29..0000000
--- a/pytest_rts/tests/evaluation/results_db.py
+++ /dev/null
@@ -1,101 +0,0 @@
-"""This module contains a class for using evaluation results database"""
-import sqlite3
-
-RESULTS_DB_FILE_NAME = "results.db"
-
-
-class ResultDatabase:
-    """Class for handling evaluation results database"""
-
-    def __init__(self):
-        self.db_conn = None
-        self.db_cursor = None
-
-    def init_conn(self):
-        """Connect sqlite3 and set cursor"""
-        self.db_conn = sqlite3.connect(RESULTS_DB_FILE_NAME)
-        self.db_cursor = self.db_conn.cursor()
-
-    def close_conn(self):
-        """Disconnect sqlite3"""
-        self.db_conn.close()
-        self.db_conn = None
-        self.db_cursor = None
-
-    def init_results_db(self):
-        """Create tables"""
-        self.db_cursor.execute(
-            """ CREATE TABLE IF NOT EXISTS project (
-                        id INTEGER PRIMARY KEY,
-                        name TEXT,
-                        commithash TEXT,
-                        test_suite_size INTEGER,
-                        database_size INTEGER,
-                        UNIQUE (name,commithash))"""
-        )
-        self.db_cursor.execute(
-            """ CREATE TABLE IF NOT EXISTS data (
-                        project_id INTEGER,
-                        lines_removed INTEGER,
-                        specific_exit_line INTEGER,
-                        specific_exit_file INTEGER,
-                        all_exit INTEGER,
-                        suite_size_line INTEGER,
-                        suite_size_file INTEGER,
-                        diff TEXT,
-                        FOREIGN KEY (project_id) REFERENCES project(id))"""
-        )
-        self.db_conn.commit()
-
-    def store_results_project(self, project_name, commithash, suite_size, db_size):
-        """Store evaluation project data and return its database id"""
-        self.db_cursor.execute(
-            """INSERT OR IGNORE INTO project (
-                  name,commithash,test_suite_size,database_size
-                ) VALUES (?,?,?,?)""",
-            (project_name, commithash, suite_size, db_size),
-        )
-        self.db_conn.commit()
-        project_id = int(
-            self.db_cursor.execute(
-                "SELECT id FROM project WHERE name = ? AND commithash = ?",
-                (project_name, commithash),
-            ).fetchone()[0]
-        )
-        return project_id
-
-    def store_results_data(
-        self,
-        project_id,
-        lines_removed,
-        specific_exit_line,
-        specific_exit_file,
-        all_exit,
-        suite_size_line,
-        suite_size_file,
-        diff,
-    ):
-        """Store evaluation data from random remove test"""
-        self.db_cursor.execute(
-            """ INSERT INTO data (
-                project_id,
-                lines_removed,
-                specific_exit_line,
-                specific_exit_file,
-                all_exit,
-                suite_size_line,
-                suite_size_file,
-                diff)
-                VALUES (?,?,?,?,?,?,?,?)""",
-            (
-                project_id,
-                lines_removed,
-                specific_exit_line,
-                specific_exit_file,
-                all_exit,
-                suite_size_line,
-                suite_size_file,
-                diff,
-            ),
-        )
-        self.db_conn.commit()
diff --git a/pytest_rts/tests/evaluation/start.py b/pytest_rts/tests/evaluation/start.py
deleted file mode 100644
index fe44e40..0000000
--- a/pytest_rts/tests/evaluation/start.py
+++ /dev/null
@@ -1,132 +0,0 @@
-"""This module contains evaluation code for the tool"""
-import logging
-import os
-import subprocess
-
-from pytest_rts.plugin import DB_FILE_NAME
-from pytest_rts.utils.git import (
-    get_current_head_hash,
-)
-from pytest_rts.tests.evaluation.results_db import (
-    ResultDatabase,
-    RESULTS_DB_FILE_NAME,
-)
-from pytest_rts.tests.evaluation.evaluation_utils import (
-    capture_all_exit_code,
-    capture_specific_exit_code,
-    delete_random_line,
-    get_all_tests_for_srcfile,
-    get_file_level_tests_between_commits,
-    full_diff_between_commits,
-    get_mapping_init_hash,
-    get_mapping_srcfiles,
-    get_srcfile_id,
-    get_test_suite_size,
-    print_remove_test_output,
-    select_random_file,
-)
-from pytest_rts.tests.testhelper import TestHelper
-
-
-EVALUATION_BRANCH = "evaluation-branch"
-MAIN_BRANCH = "master"
-
-
-def random_remove_test(iterations, deletes_per_iteration, max_wait, logger):
-    """Delete random lines and evaluate tests sets and pytest exitcodes"""
-    if not os.path.isfile(DB_FILE_NAME):
-        subprocess.run(["pytest", "--rts"], check=False)
-
-    results_db = ResultDatabase()
-    results_db.init_conn()
-    results_db.init_results_db()
-
-    test_suite_size = get_test_suite_size()
-    project_name = os.getcwd()
-    init_hash = get_mapping_init_hash()
-    db_size = os.path.getsize(DB_FILE_NAME)
-    project_id = results_db.store_results_project(
-        project_name, init_hash, test_suite_size, db_size
-    )
-
-    src_files = get_mapping_srcfiles()
-
-    testhelper = TestHelper()
-
-    for i in range(iterations):
-
-        # Remove random lines
-        testhelper.checkout_new_branch(EVALUATION_BRANCH)
-        for j in range(deletes_per_iteration):
-            random_filepath = select_random_file(src_files)
-            delete_random_line(random_filepath)
-            testhelper.commit_change(random_filepath, str(j + 1))
-
-        current_git_hash = get_current_head_hash()
-
-        # Get tests based on line-level and file-level changes
-        tests_line_level = testhelper.get_tests_from_tool_committed()
-        tests_file_level = get_file_level_tests_between_commits(
-            init_hash, current_git_hash
-        )
-
-        # Get full git diff for analysis
-        full_diff = full_diff_between_commits(init_hash, current_git_hash)
-
-        # Pytest exitcodes for running different test sets
-        exitcode_line = (
-            capture_specific_exit_code(list(tests_line_level), max_wait)
-            if tests_line_level
-            else 5
-        )
-        exitcode_file = (
-            capture_specific_exit_code(list(tests_file_level), max_wait)
-            if tests_file_level
-            else 5
-        )
-        exitcode_all = capture_all_exit_code(max_wait)
-
-        # Clear removal
-        testhelper.checkout_branch(MAIN_BRANCH)
-        testhelper.delete_branch(EVALUATION_BRANCH)
-
-        # Store and print data
-        results_db.store_results_data(
-            project_id,
-            deletes_per_iteration,
-            exitcode_line,
-            exitcode_file,
-            exitcode_all,
-            len(tests_line_level),
-            len(tests_file_level),
-            full_diff,
-        )
-        print_remove_test_output(
-            i,
-            project_name,
-            init_hash,
-            deletes_per_iteration,
-            test_suite_size,
-            len(tests_line_level),
-            len(tests_file_level),
-            exitcode_line,
-            exitcode_file,
-            exitcode_all,
-            RESULTS_DB_FILE_NAME,
-            logger,
-        )
-
-
-def main():
-    """Evaluation script entrypoint"""
-    logger = logging.getLogger()
-    logging.basicConfig(format="%(message)s", level=logging.INFO)
-    logger.info("RANDOM LINE REMOVE TESTING")
-    iterations = int(input("How many iterations? "))
-    deletes_per_iteration = int(input("How many line removals per iteration? "))
-    max_wait = int(input("Max wait time for test set running (in seconds)? "))
-    random_remove_test(iterations, deletes_per_iteration, max_wait, logger)
-
-
-if __name__ == "__main__":
-    main()
diff --git a/pytest_rts/tests/helper_project/changes/car/add_new_method.txt b/pytest_rts/tests/helper_project/changes/car/add_new_method.txt
deleted file mode 100644
index d7aa3c1..0000000
--- a/pytest_rts/tests/helper_project/changes/car/add_new_method.txt
+++ /dev/null
@@ -1,27 +0,0 @@
-class Car:
-
-    def __init__(self,seats,speed,passengers):
-        self.seats = seats
-        self.speed = speed
-        self.passengers = passengers
-
-    def get_speed(self):
-        return self.speed
-
-    def accelerate(self, amount):
-        self.speed = self.speed + amount
-
-    def get_passengers(self):
-        return self.passengers
-
-    def add_passenger(self):
-        if self.passengers + 1 <= self.seats:
-            self.passengers = self.passengers + 1
-        
-    def remove_passenger(self):
-        if self.passengers > 0:
-            self.passengers = self.passengers - 1
-
-    def new_method():
-        i = self.speed + self.seats
-        return i + 8
\ No newline at end of file
diff --git a/pytest_rts/tests/helper_project/changes/car/change_accelerate.txt b/pytest_rts/tests/helper_project/changes/car/change_accelerate.txt
deleted file mode 100644
index 40e57f0..0000000
--- a/pytest_rts/tests/helper_project/changes/car/change_accelerate.txt
+++ /dev/null
@@ -1,23 +0,0 @@
-class Car:
-
-    def __init__(self,seats,speed,passengers):
-        self.seats = seats
-        self.speed = speed
-        self.passengers = passengers
-
-    def get_speed(self):
-        return self.speed
-
-    def accelerate(self, amount):
-        self.speed = self.speed + amount - 1 + 1
-
-    def get_passengers(self):
-        return self.passengers
-
-    def add_passenger(self):
-        if self.passengers + 1 <= self.seats:
-            self.passengers = self.passengers + 1
-        
-    def remove_passenger(self):
-        if self.passengers > 0:
-            self.passengers = self.passengers - 1
diff --git a/pytest_rts/tests/helper_project/changes/car/change_accelerate_and_shift_2_forward.txt b/pytest_rts/tests/helper_project/changes/car/change_accelerate_and_shift_2_forward.txt
deleted file mode 100644
index 3011755..0000000
--- a/pytest_rts/tests/helper_project/changes/car/change_accelerate_and_shift_2_forward.txt
+++ /dev/null
@@ -1,25 +0,0 @@
-x = 1
-y = 2
-class Car:
-
-    def __init__(self,seats,speed,passengers):
-        self.seats = seats
-        self.speed = speed
-        self.passengers = passengers
-
-    def get_speed(self):
-        return self.speed
-
-    def accelerate(self, amount):
-        self.speed = self.speed + amount + 1 - 1
-
-    def get_passengers(self):
-        return self.passengers
-
-    def add_passenger(self):
-        if self.passengers + 1 <= self.seats:
-            self.passengers = self.passengers + 1
-        
-    def remove_passenger(self):
-        if self.passengers > 0:
-            self.passengers = self.passengers - 1
diff --git a/pytest_rts/tests/helper_project/changes/car/line_shifts_middle.txt b/pytest_rts/tests/helper_project/changes/car/line_shifts_middle.txt
deleted file mode 100644
index 3987655..0000000
--- a/pytest_rts/tests/helper_project/changes/car/line_shifts_middle.txt
+++ /dev/null
@@ -1,28 +0,0 @@
-class Car:
-
-    def __init__(self,seats,speed,passengers):
-        self.seats = seats
-        self.speed = speed
-        self.passengers = passengers
-
-    def get_speed(self):
-        return self.speed
-
-    def accelerate(self, amount):
-
-
-        self.speed = self.speed + amount
-
-    def get_passengers(self):
-        return self.passengers
-
-    def add_passenger(self):
-
-
-    
-        if self.passengers + 1 <= self.seats:
-            self.passengers = self.passengers + 1
-        
-    def remove_passenger(self):
-        if self.passengers > 0:
-            self.passengers = self.passengers - 1
\ No newline at end of file
diff --git a/pytest_rts/tests/helper_project/changes/car/shift_2_forward.txt b/pytest_rts/tests/helper_project/changes/car/shift_2_forward.txt
deleted file mode 100644
index 1999cb7..0000000
--- a/pytest_rts/tests/helper_project/changes/car/shift_2_forward.txt
+++ /dev/null
@@ -1,25 +0,0 @@
-x = 1
-y = 2
-class Car:
-
-    def __init__(self,seats,speed,passengers):
-        self.seats = seats
-        self.speed = speed
-        self.passengers = passengers
-
-    def get_speed(self):
-        return self.speed
-
-    def accelerate(self, amount):
-        self.speed = self.speed + amount
-
-    def get_passengers(self):
-        return self.passengers
-
-    def add_passenger(self):
-        if self.passengers + 1 <= self.seats:
-            self.passengers = self.passengers + 1
-        
-    def remove_passenger(self):
-        if self.passengers > 0:
-            self.passengers = self.passengers - 1
diff --git a/pytest_rts/tests/helper_project/changes/decorated/change_decorator.txt b/pytest_rts/tests/helper_project/changes/decorated/change_decorator.txt
deleted file mode 100644
index 4fabd30..0000000
--- a/pytest_rts/tests/helper_project/changes/decorated/change_decorator.txt
+++ /dev/null
@@ -1,29 +0,0 @@
-"""
-Decorator, to check that changes in the decorator switch on tests using
-decorated functions.
-"""
-from functools import wraps
-from typing import Callable
-
-def decrement(func: Callable[[int], int]) -> Callable[[int], int]:
-    """
-    Decrements the value returned by the decorated function.
-    """
-    @wraps(func)
-    def _wrapper(num):
-        return func(num) + 1
-
-    return _wrapper
-
-
-def modify_by(delta: int):
-    """
-    Adds delta to the value returned by the decorated function.
-    """
-    def decorator(func: Callable[[int], int]) -> Callable[[int], int]:
-        @wraps(func)
-        def _wrapper(num):
-            return func(num) + delta
-        return _wrapper
-    return decorator
-
diff --git a/pytest_rts/tests/helper_project/changes/decorated/change_decorator_2.txt b/pytest_rts/tests/helper_project/changes/decorated/change_decorator_2.txt
deleted file mode 100644
index f99eb83..0000000
--- a/pytest_rts/tests/helper_project/changes/decorated/change_decorator_2.txt
+++ /dev/null
@@ -1,29 +0,0 @@
-"""
-Decorator, to check that changes in the decorator switch on tests using
-decorated functions.
-"""
-from functools import wraps
-from typing import Callable
-
-def decrement(func: Callable[[int], int]) -> Callable[[int], int]:
-    """
-    Decrements the value returned by the decorated function.
-    """
-    @wraps(func)
-    def _wrapper(num):
-        return func(num) - 1
-
-    return _wrapper
-
-
-def modify_by(delta: int):
-    """
-    Adds delta to the value returned by the decorated function.
-    """
-    def decorator(func: Callable[[int], int]) -> Callable[[int], int]:
-        @wraps(func)
-        def _wrapper(num):
-            return func(num) * delta
-        return _wrapper
-    return decorator
-
diff --git a/pytest_rts/tests/helper_project/changes/init/change_function_one.txt b/pytest_rts/tests/helper_project/changes/init/change_function_one.txt
deleted file mode 100644
index 564ae8a..0000000
--- a/pytest_rts/tests/helper_project/changes/init/change_function_one.txt
+++ /dev/null
@@ -1,2 +0,0 @@
-def one():
-    return 2
diff --git a/pytest_rts/tests/helper_project/changes/shop/change_get_price.txt b/pytest_rts/tests/helper_project/changes/shop/change_get_price.txt
deleted file mode 100644
index 9d5e926..0000000
--- a/pytest_rts/tests/helper_project/changes/shop/change_get_price.txt
+++ /dev/null
@@ -1,38 +0,0 @@
-
-class Shop:
-
-    def __init__(self,item_price,items,money):
-        self.item_price = item_price
-        self.items = items
-        self.money = money
-
-    def buy_item(self):
-        if self.items > 0:
-            self.items = self.items - 1
-            self.money = self.money + self.item_price
-        
-    def get_items(self):
-        return self.items
-
-    def get_item_price(self):
-        return self.item_price + 1
-
-    def get_money(self):
-        return self.money
-
-    def calculate_useless_stuff(self):
-        k = 2
-        s = "ATGATATCATCGACGATGTAG"
-        context = {}  
-        for i,c in enumerate(s):
-            if (i+k >= len(s)):break
-            substring = s[i:i+k]
-            if substring not in context:
-                context[substring] = s[i+k]
-            else:
-                context[substring] = context[substring] + s[i+k]            
-    
-        return context
-
-
-    
diff --git a/pytest_rts/tests/helper_project/changes/shop/shift_2_forward.txt b/pytest_rts/tests/helper_project/changes/shop/shift_2_forward.txt
deleted file mode 100644
index 111dba0..0000000
--- a/pytest_rts/tests/helper_project/changes/shop/shift_2_forward.txt
+++ /dev/null
@@ -1,40 +0,0 @@
-x = 1
-y = 1
-
-class Shop:
-
-    def __init__(self,item_price,items,money):
-        self.item_price = item_price
-        self.items = items
-        self.money = money
-
-    def buy_item(self):
-        if self.items > 0:
-            self.items = self.items - 1
-            self.money = self.money + self.item_price
-        
-    def get_items(self):
-        return self.items
-
-    def get_item_price(self):
-        return self.item_price
-
-    def get_money(self):
-        return self.money
-
-    def calculate_useless_stuff(self):
-        k = 2
-        s = "ATGATATCATCGACGATGTAG"
-        context = {}  
-        for i,c in enumerate(s):
-            if (i+k >= len(s)):break
-            substring = s[i:i+k]
-            if substring not in context:
-                context[substring] = s[i+k]
-            else:
-                context[substring] = context[substring] + s[i+k]            
-    
-        return context
-
-
-    
diff --git a/pytest_rts/tests/helper_project/changes/test_shop/change_test_normal_shop_purchase.txt b/pytest_rts/tests/helper_project/changes/test_shop/change_test_normal_shop_purchase.txt
deleted file mode 100644
index 607bfc5..0000000
--- a/pytest_rts/tests/helper_project/changes/test_shop/change_test_normal_shop_purchase.txt
+++ /dev/null
@@ -1,34 +0,0 @@
-import pytest
-import sys
-sys.path.append(".")
-from src.shop import Shop
-
-def test_normal_shop_purchase():
-    shop = Shop(5,10,0)
-    shop.buy_item()
-    shop.buy_item()
-
-    item_price = shop.get_item_price()
-    assert shop.get_items() == 8 - 8 + 8
-    assert shop.get_money() == item_price * 2
-
-def test_normal_shop_purchase2():
-    shop = Shop(5,10,0)
-    shop.buy_item()
-    shop.buy_item()
-    shop.buy_item()
-    shop.buy_item()
-
-    item_price = shop.get_item_price()
-
-    assert shop.get_items() == 6
-    assert shop.get_money() == item_price * 4
-
-def test_empty_shop_purchase():
-    shop = Shop(5,0,0)
-    shop.buy_item()
-    assert shop.get_money() == 0
-
-	
-
-
diff --git a/pytest_rts/tests/helper_project/changes/test_shop/shift_two_forward.txt b/pytest_rts/tests/helper_project/changes/test_shop/shift_two_forward.txt
deleted file mode 100644
index 9bf83da..0000000
--- a/pytest_rts/tests/helper_project/changes/test_shop/shift_two_forward.txt
+++ /dev/null
@@ -1,32 +0,0 @@
-import pytest
-import sys
-sys.path.append(".")
-from src.shop import Shop
-
-def test_normal_shop_purchase():
-    shop = Shop(5,10,0)
-    shop.buy_item()
-    shop.buy_item()
-
-    item_price = shop.get_item_price()
-    assert shop.get_items() == 8
-    assert shop.get_money() == item_price * 2
-
-def test_normal_shop_purchase2():
-    shop = Shop(5,10,0)
-
-    
-    shop.buy_item()
-    shop.buy_item()
-    shop.buy_item()
-    shop.buy_item()
-
-    item_price = shop.get_item_price()
-
-    assert shop.get_items() == 6
-    assert shop.get_money() == item_price * 4
-
-def test_empty_shop_purchase():
-    shop = Shop(5,0,0)
-    shop.buy_item()
-    assert shop.get_money() == 0
diff --git a/pytest_rts/tests/helper_project/fake_diff_data/1.txt b/pytest_rts/tests/helper_project/fake_diff_data/1.txt
deleted file mode 100644
index d5e6315..0000000
--- a/pytest_rts/tests/helper_project/fake_diff_data/1.txt
+++ /dev/null
@@ -1,66 +0,0 @@
-diff --git a/start.py b/start.py
-index 8b05226..010a132 100644
---- a/start.py
-+++ b/start.py
-@@ -23,0 +24,2 @@ from helper import (
-+
-+
-@@ -29,0 +32,2 @@ def git_diff_data(filename,commithash1,commithash2):
-+
-+
-@@ -30,0 +35 @@ def git_diff_data(filename,commithash1,commithash2):
-+
-@@ -34,0 +40 @@ def tests_from_changed_testfiles(files,commithash1,commithash2):
-+
-@@ -35,0 +42 @@ def tests_from_changed_testfiles(files,commithash1,commithash2):
-+
-@@ -36,0 +44 @@ def tests_from_changed_testfiles(files,commithash1,commithash2):
-+
-@@ -38,0 +47 @@ def tests_from_changed_testfiles(files,commithash1,commithash2):
-+
-@@ -40,0 +50 @@ def tests_from_changed_testfiles(files,commithash1,commithash2):
-+
-@@ -50,0 +61,2 @@ def tests_from_changed_testfiles(files,commithash1,commithash2):
-+
-+
-@@ -59,0 +72 @@ def tests_from_changed_sourcefiles(files,commithash1,commithash2):
-+
-@@ -67,0 +81,2 @@ def tests_from_changed_sourcefiles(files,commithash1,commithash2):
-+
-+
-@@ -72,0 +88 @@ def tests_from_changes(commithash1,commithash2):
-+
-@@ -83,0 +100 @@ def read_newly_added_tests():
-+
-@@ -91,0 +109 @@ def read_newly_added_tests():
-+
-@@ -100,0 +119 @@ def split_changes(commit1,commit2):
-+
-@@ -109,0 +129 @@ def split_changes(commit1,commit2):
-+
-@@ -119,0 +140,2 @@ def file_changes_between_commits(commit1, commit2):
-+
-+
-@@ -135,0 +158 @@ def run_tests_and_update(test_set,update_tuple):
-+
-@@ -145,0 +169,2 @@ def commits_test():
-+
-+
-@@ -161,0 +187 @@ def commits_test():
-+
-@@ -171,0 +198 @@ def random_remove_test(iterations):
-+
-@@ -181,0 +209 @@ def random_remove_test(iterations):
-+
-@@ -190,0 +219 @@ def random_remove_test(iterations):
-+
-@@ -199,0 +229 @@ def random_remove_test(iterations):
-+
-@@ -210,0 +241 @@ def random_remove_test(iterations):
-+
-@@ -219,0 +251 @@ def random_remove_test(iterations):
-+
-@@ -228,0 +261 @@ def main():
-+
-@@ -238,0 +272 @@ def main():
-+    
diff --git a/pytest_rts/tests/helper_project/fake_diff_data/2.txt b/pytest_rts/tests/helper_project/fake_diff_data/2.txt
deleted file mode 100644
index 995b45f..0000000
--- a/pytest_rts/tests/helper_project/fake_diff_data/2.txt
+++ /dev/null
@@ -1,9 +0,0 @@
-diff --git a/start.py b/start.py
-index 8b05226..58b5c2d 100644
---- a/start.py
-+++ b/start.py
-@@ -83 +83 @@ def read_newly_added_tests():
--    conn = sqlite3.connect('example.db')
-+    conn = sqlite3.connect('example.db2')
-@@ -240,0 +241 @@ if __name__ == '__main__':
-+    
\ No newline at end of file
diff --git a/pytest_rts/tests/helper_project/fake_diff_data/3.txt b/pytest_rts/tests/helper_project/fake_diff_data/3.txt
deleted file mode 100644
index c426de0..0000000
--- a/pytest_rts/tests/helper_project/fake_diff_data/3.txt
+++ /dev/null
@@ -1,3 +0,0 @@
-@@ -16 +12,4 @@ eopigfhi0weghiweh
-@@ -24,0 +234 @@\n@@ 34,3 34,6 @@ 12312553214,,2344-123 gitqr @ oqjwd @
-@@ 13,4 22 @@
diff --git a/pytest_rts/tests/helper_project/src/decorated.py b/pytest_rts/tests/helper_project/src/decorated.py
deleted file mode 100644
index 470261a..0000000
--- a/pytest_rts/tests/helper_project/src/decorated.py
+++ /dev/null
@@ -1,17 +0,0 @@
-"""
-Decorated function, to test that changes in the decorator code switch on tests
-using the function itself.
-"""
-
-from .decorators import decrement, modify_by
-
-@decrement
-def decremented_square(num: int) -> int:
-    """Square the number and decrement the result."""
-    return num * num
-
-
-@modify_by(3)
-def modified_double(num: int) -> int:
-    """Double the number and and three to the result."""
-    return 2 * num
diff --git a/pytest_rts/tests/helper_project/src/decorators.py b/pytest_rts/tests/helper_project/src/decorators.py
deleted file mode 100644
index 8e82c97..0000000
--- a/pytest_rts/tests/helper_project/src/decorators.py
+++ /dev/null
@@ -1,29 +0,0 @@
-"""
-Decorator, to check that changes in the decorator switch on tests using
-decorated functions.
-"""
-from functools import wraps
-from typing import Callable
-
-def decrement(func: Callable[[int], int]) -> Callable[[int], int]:
-    """
-    Decrements the value returned by the decorated function.
-    """
-    @wraps(func)
-    def _wrapper(num):
-        return func(num) - 1
-
-    return _wrapper
-
-
-def modify_by(delta: int):
-    """
-    Adds delta to the value returned by the decorated function.
-    """
-    def decorator(func: Callable[[int], int]) -> Callable[[int], int]:
-        @wraps(func)
-        def _wrapper(num):
-            return func(num) + delta
-        return _wrapper
-    return decorator
-
diff --git a/pytest_rts/tests/helper_project/tests/test_decorated.py b/pytest_rts/tests/helper_project/tests/test_decorated.py
deleted file mode 100644
index c6e6df6..0000000
--- a/pytest_rts/tests/helper_project/tests/test_decorated.py
+++ /dev/null
@@ -1,18 +0,0 @@
-"""
-Test for decorated function.
-"""
-from src import decorated
-
-
-def test_decorated():
-    """
-    Test that decremented square of 3 is 8.
-    """
-    assert decorated.decremented_square(3) == 8
-
-
-def test_decorated_2():
-    """
-    Test that 2 * 5 + 3 = 13
-    """
-    assert decorated.modified_double(5) == 13
diff --git a/pytest_rts/tests/helper_project/tests/test_init.py b/pytest_rts/tests/helper_project/tests/test_init.py
deleted file mode 100644
index aacea13..0000000
--- a/pytest_rts/tests/helper_project/tests/test_init.py
+++ /dev/null
@@ -1,5 +0,0 @@
-from src import one
-
-
-def test_one():
-    assert one() == 1
diff --git a/pytest_rts/tests/test_common.py b/pytest_rts/tests/test_common.py
index 75d5282..1db4dc0 100644
--- a/pytest_rts/tests/test_common.py
+++ b/pytest_rts/tests/test_common.py
@@ -1,61 +1,69 @@
-import ast
+"""Tests for common utility functions"""
+from typing import cast
+
 import pytest
-from pytest_rts.utils import git, common
-
-
-def test_line_mapping(helper):
-    helper.change_file("changes/car/shift_2_forward.txt", "src/car.py")
-
-    diff = git.file_diff_data_current("src/car.py")
-    lines_to_query, updates_to_lines, _ = git.get_test_lines_and_update_lines(diff)
-    line_map = common.line_mapping(updates_to_lines, "src/car.py")
-
-    expected_line_map = {
-        1: 3,
-        2: 4,
-        3: 5,
-        4: 6,
-        5: 7,
-        6: 8,
-        7: 9,
-        8: 10,
-        9: 11,
-        10: 12,
-        11: 13,
-        12: 14,
-        13: 15,
-        14: 16,
-        15: 17,
-        16: 18,
-        17: 19,
-        18: 20,
-        19: 21,
-        20: 22,
-        21: 23,
-        22: 24,
-        23: 25,
-        24: 26,
-        25: 27,
-    }
+from _pytest.nodes import Item
+
+from pytest_rts.utils.common import filter_pytest_items, strip_pytest_cov_testname
+
 
-    assert line_map == expected_line_map
+@pytest.mark.parametrize(
+    "testname, expected",
+    [
+        (
+            "tests/test_example.py::test_methods_var_inheritance|setup",
+            "tests/test_example.py::test_methods_var_inheritance",
+        ),
+        (
+            "tests/test_example2.py::TestJSON::test_jsonify_basic_types[0]|teardown",
+            "tests/test_example2.py::TestJSON::test_jsonify_basic_types[0]",
+        ),
+        (
+            "tests/test_example3.py::test_session_ip_warning|run",
+            "tests/test_example3.py::test_session_ip_warning",
+        ),
+    ],
+)
+def test_strip_pytest_cov_testname(testname: str, expected: str) -> None:
+    """Test pytest-cov testname stripping to actual pytest item.nodeid strings"""
+    assert strip_pytest_cov_testname(testname) == expected
 
 
-def test_function_lines():
-    with open("src/car.py", "r") as f:
-        code = f.read()
-        codelines = f.readlines()
+def test_filter_pytest_items() -> None:
+    """Test for filtering the test set
+    based on given existing tests
+    """
 
-    parsed_code = ast.parse(code)
-    func_lines = common.function_lines(parsed_code, len(codelines))
+    class FakePytestItem:  # pylint: disable=too-few-public-methods
+        """Class that has nodeid field like a pytest item
+        and a method get_closest_marker which returns something
+        """
 
-    expected_func_lines = [
-        ("__init__", 4, 7),
-        ("get_speed", 9, 10),
-        ("accelerate", 12, 13),
-        ("get_passengers", 15, 16),
-        ("add_passenger", 18, 20),
-        ("remove_passenger", 22, 0),
+        def __init__(self, name: str, nodeid: str, markername: str) -> None:
+            """Set test name, identifier nodeid and marker name"""
+            self.name = name
+            self.nodeid = nodeid
+            self.markername = markername
+
+        def get_closest_marker(self, markername: str) -> bool:
+            """Return if item is marked as skipped"""
+            if self.markername == markername:
+                return True
+            return False
+
+    collected_items = [
+        cast(Item, FakePytestItem("test1", "test_func_1", "")),
+        cast(Item, FakePytestItem("test2", "test_func_2", "skip")),
+        cast(Item, FakePytestItem("test3", "test_func_3", "")),
+        cast(Item, FakePytestItem("test4", "test_func_4", "skipif")),
+        cast(Item, FakePytestItem("test5", "test_func_5", "")),
     ]
+    existing_tests = {
+        "test_func_1",
+        "test_func_3",
+    }
+
+    filtered_items = filter_pytest_items(collected_items, existing_tests)
 
-    assert func_lines == expected_func_lines
+    assert len(filtered_items) == 1
+    assert filtered_items[0].nodeid == "test_func_5"
diff --git a/pytest_rts/tests/test_e2e.py b/pytest_rts/tests/test_e2e.py
index b9f8754..725dd7a 100644
--- a/pytest_rts/tests/test_e2e.py
+++ b/pytest_rts/tests/test_e2e.py
@@ -1,215 +1,34 @@
-import pytest
+"""Integration tests for pytest-rts"""
+import os
 
+from _pytest.pytester import Testdir
 
-def test_full_integration(helper):
-    helper.checkout_new_branch()
 
-    # Add a new method to source file
-    helper.change_file("changes/car/add_new_method.txt", "src/car.py")
-
-    # Get changed src file id
-    src_file_id = helper.get_mapping_id_from_filename("src/car.py", is_srcfile=True)
-
-    # Get working directory test_set like in pytest_rts script
-    workdir_test_set = helper.get_tests_from_tool_current()
-
-    # New method addition = no new tests should be found
-    assert not workdir_test_set
-
-    # Run pytest_rts, db shouldn't update
-    old_srcfile_lines = helper.get_mapping_lines_for_srcfile(src_file_id)
-    helper.run_tool()
-    new_srcfile_lines = helper.get_mapping_lines_for_srcfile(src_file_id)
-
-    assert old_srcfile_lines == new_srcfile_lines
-
-    # Commit changes
-    helper.commit_change("src/car.py", "new_method_src")
-
-    # Get committed changes test_set like in pytest_rts script
-    commit_test_set = helper.get_tests_from_tool_committed()
-
-    # New method addition = no new tests should be found
-    assert not commit_test_set
-
-    # DB should update after running test selector
-    # But no new test tests new method so lines should be the same
-    helper.run_tool()
-    new_srcfile_lines = helper.get_mapping_lines_for_srcfile(src_file_id)
-    assert old_srcfile_lines == new_srcfile_lines
-
-    # Add a new test method
-    helper.change_file("changes/test_car/add_test_passengers.txt", "tests/test_car.py")
-
-    # Get working directory diffs and test_set like in pytest_rts script
-    workdir_test_set2 = helper.get_tests_from_tool_current()
-
-    # Changes test_set should be empty
-    assert not workdir_test_set2
-
-    # Running pytest_rts should not add new test to database
-    helper.run_tool()
-    assert not helper.new_test_exists_in_mapping_db(
-        "tests/test_car.py::test_passengers"
-    )
-
-    # Commit changes
-    helper.commit_change("tests/test_car.py", "new_test_method")
-
-    # Get committed changes test_set like in pytest_rts script
-    commit_test_set2 = helper.get_tests_from_tool_committed()
-
-    # Test_set should now include all tests from changes between this commit and previous
-    # = New test method
-    assert commit_test_set2 == {"tests/test_car.py::test_passengers"}
-
-    # New tests should include the newly added test only
-    new_tests = helper.get_newly_added_tests_from_tool()
-    assert new_tests == {"tests/test_car.py::test_passengers"}
-
-    # Running pytest_rts should now update database = new test function should be found in db
-    helper.run_tool()
-    assert helper.new_test_exists_in_mapping_db("tests/test_car.py::test_passengers")
-
-
-def test_db_updating_only_once(helper):
-    helper.checkout_new_branch()
-
-    filename = "src/car.py"
-    change = "changes/car/shift_2_forward.txt"
-    expected_lines = [6, 7, 8, 11, 14]
-
-    src_file_id = helper.get_mapping_id_from_filename(filename, is_srcfile=True)
-    old_lines = helper.get_mapping_lines_for_srcfile(src_file_id)
-
-    # Change src file
-    helper.change_file(change, filename)
-
-    # Changes in working directory, run pytest_rts
-    # Shouldn't update db
-    helper.run_tool()
-    new_lines = helper.get_mapping_lines_for_srcfile(src_file_id)
-    assert old_lines == new_lines
-
-    # Commit changes
-    helper.commit_change(filename, "commit1")
-
-    # Committed changes, run pytest_rts
-    # Should update db
-    helper.run_tool()
-    new_lines = helper.get_mapping_lines_for_srcfile(src_file_id)
-    assert old_lines != new_lines
-    assert new_lines == expected_lines
-
-    # Run again, shouldn't update db
-    helper.run_tool()
-    new_lines = helper.get_mapping_lines_for_srcfile(src_file_id)
-    assert new_lines == expected_lines
-
-
-def test_skipping_commit(helper):
-    # Checkout a new branch
-    helper.checkout_new_branch()
-
-    # Change file from changes folder and commit changes
-    first_change, first_filename = (
-        "changes/car/change_accelerate.txt",
-        "src/car.py",
-    )
-    helper.change_file(first_change, first_filename)
-    helper.commit_change(first_filename, "commit1")
-
-    # Run tests selector and db should update
-    helper.run_tool()
-
-    # Change shop.py from changes folder and commit changes
-    second_change, second_filename = (
-        "changes/shop/change_get_price.txt",
-        "src/shop.py",
-    )
-    helper.change_file(second_change, second_filename)
-    helper.commit_change(second_filename, "commit2")
-
-    # Change test_car.py from changes folder and commit changes
-    third_change, third_filename = (
-        "changes/test_car/add_test_passengers.txt",
-        "tests/test_car.py",
-    )
-    helper.change_file(third_change, third_filename)
-    helper.commit_change(third_filename, "commit3")
-
-    # Tests selectors functions should find tests from changes:
-    # Commit1 -> Commit2 AND Commit2 -> Commit3
-    # DB required to use the function
-    test_set = helper.get_tests_from_tool_committed()
-    assert test_set == {
-        "tests/test_shop.py::test_normal_shop_purchase2",
-        "tests/test_shop.py::test_normal_shop_purchase",
-        "tests/test_car.py::test_passengers",
-    }
-
-
-def test_squashing_commits(helper):
-    helper.checkout_new_branch()
-
-    helper.change_file("changes/car/change_accelerate.txt", "src/car.py")
-    helper.commit_change("src/car.py", "commit0")
-
-    helper.change_file("changes/car/add_new_method.txt", "src/car.py")
-    helper.commit_change("src/car.py", "commit1")
-
-    # Run tool -> db updated to commit1 state
-    helper.run_tool()
-
-    helper.change_file("changes/shop/change_get_price.txt", "src/shop.py")
-    helper.commit_change("src/shop.py", "commit2")
-
-    helper.squash_commits(3, "commit3")
-
-    # Tool should find only tests for change introduced in commit1 -> commit2
-    assert helper.get_tests_from_tool_committed() == {
-        "tests/test_shop.py::test_normal_shop_purchase",
-        "tests/test_shop.py::test_normal_shop_purchase2",
-    }
-
-
-def test_init_code_tracked(helper):
-    helper.change_file("changes/init/change_function_one.txt", "src/__init__.py")
-    assert helper.get_tests_from_tool_current() == {"tests/test_init.py::test_one"}
-
-
-def test_decorated_tracked(helper):
-    """Test that changes in the decorator switch on the test using decorated
-    function.
+def test_only_new_functions_are_ran(testdir: Testdir) -> None:
+    """Test case for running pytest-rts when new tests are added
+    and changes are not committed.
     """
-    helper.change_file("changes/decorated/change_decorator.txt", "src/decorators.py")
-    assert helper.get_tests_from_tool_current() == {
-        "tests/test_decorated.py::test_decorated"
-    }
+    # copy the helper project
+    testdir.copy_example(".")
 
+    # run pytest pytest-cov to produce mapping
+    # subprocess used to not mess up with coverage for this test suite
+    testdir.runpytest_subprocess("--cov=.", "--cov-context=test")
 
-def test_decorated_with_param_tracked(helper):
-    """Test that changes in the parametrized decorator switch on the test using
-    decorated function.
-    """
-    helper.change_file("changes/decorated/change_decorator_2.txt", "src/decorators.py")
-    assert helper.get_tests_from_tool_current() == {
-        "tests/test_decorated.py::test_decorated_2"
-    }
+    # rename .coverage file produced by pytest-cov
+    os.rename(".coverage", "rts-coverage.1234")
 
+    # add a new test method to an existing file
+    os.rename("changes/test_car/add_test_passengers.txt", "tests/test_car.py")
 
-def test_testfunction_runtimes_not_wiped(helper):
-    """Test that checks that test function runtimes are not removed
-    from database when running the tool for committed changes
-    and a testfile is changed
+    # add a new test file with a test in it
+    testdir.makepyfile(
+        """
+        def test_empty():
+            assert 1 == 1
     """
-    orig_runtimes = helper.get_test_function_runtimes()
-    helper.checkout_new_branch()
-
-    helper.change_file("changes/test_shop/shift_two_forward.txt", "tests/test_shop.py")
-    helper.commit_change("tests/test_shop.py", "shift")
-
-    helper.run_tool()
-    new_runtimes = helper.get_test_function_runtimes()
+    )
 
-    assert orig_runtimes == new_runtimes
+    # run pytest-rts to only run new tests
+    result = testdir.runpytest("--rts", "--rts-coverage-db=rts-coverage.1234")
+    result.assert_outcomes(passed=2, failed=0, errors=0)
diff --git a/pytest_rts/tests/test_git.py b/pytest_rts/tests/test_git.py
deleted file mode 100644
index 0ec0091..0000000
--- a/pytest_rts/tests/test_git.py
+++ /dev/null
@@ -1,114 +0,0 @@
-import pytest
-from pytest_rts.utils import git
-
-
-@pytest.mark.parametrize(
-    "changes, expected",
-    [
-        ([("changes/car/shift_2_forward.txt", "src/car.py")], ["src/car.py"]),
-        ([], []),
-        (
-            [
-                ("changes/car/shift_2_forward.txt", "src/car.py"),
-                ("changes/shop/change_get_price.txt", "src/shop.py"),
-            ],
-            ["src/car.py", "src/shop.py"],
-        ),
-    ],
-)
-def test_changed_files_current(changes, expected, helper):
-    for c in changes:
-        change = c[0]
-        filename = c[1]
-        helper.change_file(change, filename)
-    assert git.changed_files_current() == expected
-
-
-@pytest.mark.parametrize(
-    "diff_file, real_changed_lines, real_line_updates",
-    [
-        (
-            "fake_diff_data/1.txt",
-            [
-                23,
-                29,
-                30,
-                34,
-                35,
-                36,
-                38,
-                40,
-                50,
-                59,
-                67,
-                72,
-                83,
-                91,
-                100,
-                109,
-                119,
-                135,
-                145,
-                161,
-                171,
-                181,
-                190,
-                199,
-                210,
-                219,
-                228,
-                238,
-            ],
-            [
-                (23, 2),
-                (29, 4),
-                (30, 5),
-                (34, 6),
-                (35, 7),
-                (36, 8),
-                (38, 9),
-                (40, 10),
-                (50, 12),
-                (59, 13),
-                (67, 15),
-                (72, 16),
-                (83, 17),
-                (91, 18),
-                (100, 19),
-                (109, 20),
-                (119, 22),
-                (135, 23),
-                (145, 25),
-                (161, 26),
-                (171, 27),
-                (181, 28),
-                (190, 29),
-                (199, 30),
-                (210, 31),
-                (219, 32),
-                (228, 33),
-                (238, 34),
-            ],
-        ),
-        ("fake_diff_data/2.txt", [83, 240], [(83, 0), (240, 1)]),
-        ("fake_diff_data/3.txt", [16, 24], [(16, 3), (24, 4)]),
-    ],
-)
-def test_get_test_lines_and_update_lines_fake_change(
-    diff_file, real_changed_lines, real_line_updates
-):
-    with open(diff_file, "r") as f:
-        diff = f.read()
-
-    lines_changed, line_updates, _ = git.get_test_lines_and_update_lines(diff)
-
-    assert lines_changed == real_changed_lines
-    assert line_updates == real_line_updates
-
-
-def test_get_test_lines_and_update_lines_real_change(helper):
-    helper.change_file("changes/car/line_shifts_middle.txt", "src/car.py")
-    diff = git.file_diff_data_current("src/car.py")
-    changed_lines, line_updates, _ = git.get_test_lines_and_update_lines(diff)
-    assert changed_lines == [11, 17]
-    assert line_updates == [(11, 2), (17, 5)]
diff --git a/pytest_rts/tests/testhelper.py b/pytest_rts/tests/testhelper.py
deleted file mode 100644
index a92cbd6..0000000
--- a/pytest_rts/tests/testhelper.py
+++ /dev/null
@@ -1,128 +0,0 @@
-import sqlite3
-import subprocess
-from pytest_rts.plugin import DB_FILE_NAME
-from pytest_rts.utils.common import run_new_test_collection
-from pytest_rts.utils.selection import (
-    get_tests_and_data_committed,
-    get_tests_and_data_current,
-)
-from pytest_rts.utils.mappinghelper import MappingHelper
-from pytest_rts.utils.testgetter import TestGetter
-
-
-class TestHelper:
-    def get_mapping_id_from_filename(self, filename, is_srcfile):
-        if is_srcfile:
-            sql = "SELECT id FROM src_file WHERE path = ?"
-        else:
-            sql = "SELECT id from test_file WHERE path = ?"
-
-        conn = sqlite3.connect(DB_FILE_NAME)
-        file_id = conn.execute(sql, (filename,)).fetchone()[0]
-        conn.close()
-        return file_id
-
-    def get_mapping_lines_for_srcfile(self, src_file_id):
-        conn = sqlite3.connect(DB_FILE_NAME)
-        lines = [
-            x[0]
-            for x in conn.execute(
-                "SELECT line_id FROM test_map WHERE file_id = ?", (src_file_id,)
-            ).fetchall()
-        ]
-        conn.close()
-        return lines
-
-    def get_tests_from_tool_current(self):
-        conn = sqlite3.connect(DB_FILE_NAME)
-        mappinghelper = MappingHelper(conn)
-        testgetter = TestGetter(conn)
-        change_data = get_tests_and_data_current(mappinghelper, testgetter)
-        conn.close()
-        return change_data.test_set
-
-    def get_tests_from_tool_committed(self):
-        conn = sqlite3.connect(DB_FILE_NAME)
-        mappinghelper = MappingHelper(conn)
-        testgetter = TestGetter(conn)
-        change_data = get_tests_and_data_committed(
-            mappinghelper,
-            testgetter,
-        )
-        conn.close()
-        return change_data.test_set
-
-    def get_newly_added_tests_from_tool(self):
-        run_new_test_collection()
-        conn = sqlite3.connect(DB_FILE_NAME)
-        testgetter = TestGetter(conn)
-        new_tests = testgetter.newly_added_tests
-        conn.close()
-        return new_tests
-
-    def new_test_exists_in_mapping_db(self, testname):
-        conn = sqlite3.connect(DB_FILE_NAME)
-        sql = "SELECT EXISTS(SELECT id FROM test_function WHERE context = ?)"
-        exists = bool(conn.execute(sql, (testname,)).fetchone()[0])
-        conn.close()
-        return exists
-
-    def change_file(self, change_path, file_path):
-        subprocess.run(
-            ["cp", "-f", change_path, file_path],
-            check=True,
-            stdout=subprocess.DEVNULL,
-            stderr=subprocess.DEVNULL,
-        )
-
-    def commit_change(self, filename, message):
-        subprocess.run(
-            ["git", "add", filename],
-            check=True,
-            stdout=subprocess.DEVNULL,
-            stderr=subprocess.DEVNULL,
-        )
-        subprocess.run(
-            ["git", "commit", "-m", message],
-            check=True,
-            stdout=subprocess.DEVNULL,
-            stderr=subprocess.DEVNULL,
-        )
-
-    def run_tool(self):
-        subprocess.run(["pytest", "--rts"], check=True)
-
-    def squash_commits(self, n, new_message):
-        subprocess.run(["git", "reset", "--soft", f"HEAD~{n}"], check=True)
-        subprocess.run(["git", "commit", "-m", new_message], check=True)
-
-    def checkout_new_branch(self, branchname="new-branch"):
-        subprocess.run(
-            ["git", "checkout", "-b", branchname],
-            check=True,
-            stdout=subprocess.DEVNULL,
-            stderr=subprocess.DEVNULL,
-        )
-
-    def checkout_branch(self, branchname):
-        subprocess.run(
-            ["git", "checkout", branchname],
-            check=True,
-            stdout=subprocess.DEVNULL,
-            stderr=subprocess.DEVNULL,
-        )
-
-    def delete_branch(self, branchname):
-        subprocess.run(
-            ["git", "branch", "-D", branchname],
-            check=False,
-            stdout=subprocess.DEVNULL,
-            stderr=subprocess.DEVNULL,
-        )
-
-    def get_test_function_runtimes(self):
-        conn = sqlite3.connect(DB_FILE_NAME)
-        testgetter = TestGetter(conn)
-        runtimes = testgetter.test_function_runtimes
-        conn.close()
-        return runtimes
diff --git a/pytest_rts/utils/common.py b/pytest_rts/utils/common.py
index f66373d..3a246cf 100644
--- a/pytest_rts/utils/common.py
+++ b/pytest_rts/utils/common.py
@@ -1,176 +1,43 @@
 """This module contains fuctions for test selecting operations"""
-import ast
-import os
-import subprocess
-import sys
-from typing import Dict, List, Set, Tuple
+from typing import List, Set
 
+from coverage import CoverageData
 from _pytest.nodes import Item
 
-from pytest_rts.utils.git import (
-    file_diff_data_between_commits,
-    file_diff_data_current,
-    get_test_lines_and_update_lines,
-)
 
-
-def file_diff_dict_current(files) -> Dict[int, str]:
-    """Returns a dictionary with file id as key and git diff as value"""
-    return {file_id: file_diff_data_current(filename) for file_id, filename in files}
-
-
-def file_diff_dict_between_commits(files, commithash1, commithash2) -> Dict[int, str]:
-    """Returns a dictionary with file id as key and git diff as value"""
-    return {
-        file_id: file_diff_data_between_commits(filename, commithash1, commithash2)
-        for file_id, filename in files
-    }
-
-
-def tests_from_changed_testfiles(
-    diff_dict, files, testgetter
-) -> Tuple[Set[str], Dict[int, List[int]], Dict[int, Dict[int, int]]]:
-    """Calculate test set and update data from changes to a testfile"""
-
-    test_set: Set[str] = set()
-    changed_lines_map: Dict[int, List[int]] = {}
-    new_line_map: Dict[int, Dict[int, int]] = {}
-    for testfile in files:
-        file_id = testfile[0]
-        filename = testfile[1]
-        changed_lines, updates_to_lines, _ = get_test_lines_and_update_lines(
-            diff_dict[file_id]
+def filter_pytest_items(
+    pytest_items: List[Item], existing_tests: Set[str]
+) -> List[Item]:
+    """Select pytest items if they are new and not marked as skipped"""
+    return list(
+        filter(
+            lambda item: item.nodeid not in existing_tests
+            and not item.get_closest_marker("skipif")
+            and not item.get_closest_marker("skip"),
+            pytest_items,
         )
-
-        changed_lines_map[file_id] = changed_lines
-        new_line_map[file_id] = line_mapping(updates_to_lines, filename)
-
-        test_set.update(testgetter.get_tests_from_testfiles(changed_lines, file_id))
-
-    return test_set, changed_lines_map, new_line_map
+    )
 
 
-def tests_from_changed_srcfiles(
-    diff_dict, files, mappinghelper, testgetter
-) -> Tuple[Set[str], Dict[int, List[int]], Dict[int, Dict[int, int]], List[str]]:
+def get_existing_tests(coverage_file_path: str) -> Set[str]:
+    """Read all the test function names from the coverage file.
+    pytest-cov creates the coverage file and adds a section at the
+    end of each testname which need to be stripped.
     """
-    Calculate test set,
-    update data
-    and warning for untested new lines from changes to a source code file
-    """
-
-    test_set: Set[str] = set()
-    changed_lines_map: Dict[int, List[int]] = {}
-    new_line_map: Dict[int, Dict[int, int]] = {}
-    files_to_warn: List[str] = []
-    for srcfile in files:
-        file_id = srcfile[0]
-        filename = srcfile[1]
-        changed_lines, updates_to_lines, new_lines = get_test_lines_and_update_lines(
-            diff_dict[file_id]
-        )
-
-        changed_lines_map[file_id] = changed_lines
-        new_line_map[file_id] = line_mapping(updates_to_lines, filename)
-
-        if not all(
-            mappinghelper.line_exists(file_id, line_number) for line_number in new_lines
-        ):
-            files_to_warn.append(filename)
-
-        test_set.update(testgetter.get_tests_from_srcfiles(changed_lines, file_id))
-
-    return test_set, changed_lines_map, new_line_map, files_to_warn
-
-
-def split_changes(
-    changed_files, mappinghelper
-) -> Tuple[List[Tuple[int, str]], List[Tuple[int, str]]]:
-    """Split given changed files into changed testfiles and source code files by comparing paths"""
-    changed_testfiles = [x for x in mappinghelper.testfiles if x[1] in changed_files]
-    changed_srcfiles = [x for x in mappinghelper.srcfiles if x[1] in changed_files]
-    return changed_testfiles, changed_srcfiles
-
-
-def run_new_test_collection():
-    """Run collect plugin"""
-    subprocess.run(["pytest_rts_collect"], check=True)
-
-
-def line_mapping(updates_to_lines, filename, project_folder=".") -> Dict[int, int]:
-    """Calculate new line numbers from given changes"""
-    try:
-        with open(os.path.join(".", project_folder, filename)) as filetoread:
-            line_count = len(filetoread.readlines())
-    except OSError:
-        return {}
-    new_line_mapping = {}
-    for i, _ in enumerate(updates_to_lines):
-        if i + 1 >= len(updates_to_lines):
-            next_point = line_count
-        else:
-            next_point = updates_to_lines[i + 1][0]
-
-        current = updates_to_lines[i][0]
-        diff = updates_to_lines[i][1]
-
-        if diff == 0:
-            continue
-        for k in range(current + 1, next_point + 1):
-            new_line_mapping[k] = k + diff
-
-    return new_line_mapping
-
-
-def function_lines(node, end):
-    """Calculate start and end line numbers for python functions"""
-
-    def _next_lineno(i, end):
-        try:
-            return node[i + 1].decorator_list[0].lineno - 1
-        except (IndexError, AttributeError):
-            pass
-
-        try:
-            return node[i + 1].lineno - 1
-        except IndexError:
-            return end
-        except AttributeError:
-            return None
-
-    result = []
-
-    if isinstance(node, ast.AST):
-        if (
-            node.__class__.__name__ == "FunctionDef"
-            or node.__class__.__name__ == "AsyncFunctionDef"
-        ):
-            result.append((node.name, node.body[0].lineno, end))
-
-        for _, field_value in ast.iter_fields(node):
-            result.extend(function_lines(field_value, end))
-
-    elif isinstance(node, list):
-        for i, item in enumerate(node):
-            result.extend(function_lines(item, _next_lineno(i, end)))
-
-    return result
-
-
-def calculate_func_lines(src_code) -> Dict[str, Tuple[int, int]]:
-    """Calculate start and end line numbers for all functions in given code string"""
-    parsed_src_code = ast.parse(src_code)
-    func_lines = function_lines(parsed_src_code, len(src_code.splitlines()))
-    return {x[0]: (x[1], x[2]) for x in func_lines}
+    coverage_data = CoverageData(coverage_file_path)
+    coverage_data.read()
+    return {
+        strip_pytest_cov_testname(testname)
+        for testname in coverage_data.measured_contexts()
+    }
 
 
-def filter_and_sort_pytest_items(test_set, pytest_items, runtimes) -> List[Item]:
-    """Selected pytest items based on found tests
-    ordered by their runtimes
-    """
-    selected = list(filter(lambda item: item.nodeid in test_set, pytest_items))
-    updated_runtimes = {
-        item.nodeid: runtimes[item.nodeid] if item.nodeid in runtimes else sys.maxsize
-        for item in pytest_items
-    }
-    return sorted(selected, key=lambda item: updated_runtimes[item.nodeid])
+def strip_pytest_cov_testname(testname: str) -> str:
+    """Strip ends of pytest-cov produced testnames"""
+    if testname.endswith("|teardown"):
+        return testname[:-9]
+    if testname.endswith("|setup"):
+        return testname[:-6]
+    if testname.endswith("|run"):
+        return testname[:-4]
+    return testname
diff --git a/pytest_rts/utils/git.py b/pytest_rts/utils/git.py
deleted file mode 100644
index 08c8d2e..0000000
--- a/pytest_rts/utils/git.py
+++ /dev/null
@@ -1,120 +0,0 @@
-"""This module contains code for git operations"""
-import re
-import subprocess
-from pydriller import GitRepository
-
-
-def get_git_repo(project_folder):
-    """Return a GitRepository"""
-    if not project_folder:
-        res = subprocess.check_output(
-            "git rev-parse --show-toplevel".split(),
-            stderr=subprocess.DEVNULL,
-        )
-        project_folder = res.decode().strip()
-    return GitRepository(project_folder)
-
-
-def is_git_repo():
-    """Check if current directory or any parent directory is a git repo"""
-    try:
-        subprocess.check_output(
-            "git rev-parse --show-toplevel".split(),
-            stderr=subprocess.DEVNULL,
-        )
-        return True
-    except subprocess.CalledProcessError:
-        return False
-
-
-def repo_has_commits():
-    """Check if current repository has commits"""
-    try:
-        subprocess.check_output(
-            ["git", "log"],
-            stderr=subprocess.DEVNULL,
-        )
-        return True
-    except subprocess.CalledProcessError:
-        return False
-
-
-def changed_files_between_commits(commit1, commit2, project_folder=None):
-    """Get changed files between two commits"""
-    repo = get_git_repo(project_folder)
-    return repo.repo.git.diff("--name-only", commit1, commit2).split()
-
-
-def changed_files_current(project_folder=None):
-    """Get changed files in git working directory"""
-    repo = get_git_repo(project_folder)
-    return repo.repo.git.diff("--name-only").split()
-
-
-def file_diff_data_between_commits(
-    filename, commithash1, commithash2, project_folder=None
-):
-    """Get git diff for a file from changes between two commits"""
-    repo = get_git_repo(project_folder)
-    return repo.repo.git.diff("-U0", commithash1, commithash2, "--", filename)
-
-
-def file_diff_data_current(filename, project_folder=None):
-    """Get git diff for a file in git working directory"""
-    repo = get_git_repo(project_folder)
-    return repo.repo.git.diff("-U0", "--", filename)
-
-
-def get_test_lines_and_update_lines(diff):
-    """Parse changed lines, line number updates and new lines from git diff -U0 output"""
-    regex = r"[@][@]\s+[-][0-9]+(?:,[0-9]+)?\s+[+][0-9]+(?:,[0-9]+)?\s+[@][@]"
-    line_changes = re.findall(regex, diff)
-    lines_to_query = []
-    updates_to_lines = []
-    new_lines = []
-    cum_diff = 0
-    for change in line_changes:
-        changed_line = change.strip("@").split()
-        if "," not in changed_line[0]:
-            changed_line[0] += ",1"
-        if "," not in changed_line[1]:
-            changed_line[1] += ",1"
-        old = changed_line[0].split(",")
-        old[0] = old[0].strip("-")
-        new = changed_line[1].split(",")
-        new[0] = new[0].strip("+")
-
-        line_diff = (
-            ((int(new[0]) + int(new[1])) - int(new[0]))
-            - ((int(old[0]) + int(old[1])) - int(old[0]))
-            + cum_diff
-        )
-        cum_diff = line_diff
-
-        update_tuple = (int(old[0]), line_diff)
-        updates_to_lines.append(update_tuple)
-
-        # example data:
-        # @@ -old0,old1 +new0,new1 @@
-        # old0 to old0 + old1 are now new0 to new0+new1
-        # changed lines: old0 to old0 + old1
-        # correct?
-        if int(old[1]) == 0:
-            lines_to_query.append(int(old[0]))
-        else:
-            for i in range(int(old[0]), int(old[0]) + int(old[1])):
-                lines_to_query.append(i)
-
-        # Extract new lines
-        if int(new[1]) == 0:
-            new_lines.append(int(new[0]))
-        else:
-            for i in range(int(new[0]), int(new[0]) + int(new[1])):
-                new_lines.append(i)
-
-    return lines_to_query, updates_to_lines, new_lines
-
-
-def get_current_head_hash():
-    """Return current git HEAD hash"""
-    return get_git_repo(None).repo.head.object.hexsha
diff --git a/pytest_rts/utils/mappinghelper.py b/pytest_rts/utils/mappinghelper.py
deleted file mode 100644
index 8656227..0000000
--- a/pytest_rts/utils/mappinghelper.py
+++ /dev/null
@@ -1,300 +0,0 @@
-"""Module for MappingHelper class"""
-import os
-from typing import Dict, List, NamedTuple, Set, Tuple
-
-from coverage import CoverageData
-from _pytest.python import Function
-
-TestrunData = NamedTuple(
-    "TestrunData",
-    [
-        ("pytest_item", Function),
-        ("elapsed_time", float),
-        ("coverage_data", CoverageData),
-        ("found_testfiles", Set[str]),
-        ("test_function_lines", Dict[str, Dict[str, Tuple[int, int]]]),
-    ],
-)
-
-TestFunctionData = NamedTuple(
-    "TestFunctionData",
-    [
-        ("testfile_id", int),
-        ("testname", str),
-        ("start_line_number", int),
-        ("end_line_number", int),
-        ("elapsed_time", float),
-    ],
-)
-
-
-class MappingHelper:
-    """Class to handle mapping database initialization and updating"""
-
-    def __init__(self, connection):
-        """Set the connection"""
-        self.connection = connection
-
-    @property
-    def srcfiles(self) -> List[Tuple[int, str]]:
-        """List of source code files (id, path) in the mapping database"""
-        return [
-            (x[0], x[1])
-            for x in self.connection.execute("SELECT id, path FROM src_file").fetchall()
-        ]
-
-    @property
-    def testfiles(self) -> List[Tuple[int, str]]:
-        """List of test code files (id, path) in the mapping database"""
-        return [
-            (x[0], x[1])
-            for x in self.connection.execute(
-                "SELECT id, path FROM test_file"
-            ).fetchall()
-        ]
-
-    @property
-    def last_update_hash(self) -> str:
-        """Git commit hash of latest database update"""
-        return self.connection.execute("SELECT hash FROM last_update_hash").fetchone()[
-            0
-        ]
-
-    def _delete_lines(self, line_ids, file_id):
-        """Remove entries from covered line mapping"""
-        entries = [(line_id, file_id) for line_id in line_ids]
-        self.connection.executemany(
-            "DELETE FROM test_map WHERE line_id == ? AND file_id == ?",
-            entries,
-        )
-
-    def _add_lines(self, src_id, test_function_id, lines):
-        """Add entries to covered line mapping"""
-        entries = [(src_id, test_function_id, line) for line in lines]
-        self.connection.executemany(
-            "INSERT OR IGNORE INTO test_map (file_id,test_function_id,line_id) VALUES (?,?,?)",
-            entries,
-        )
-
-    def _add_srcfile(self, path):
-        """Add a covered source code file to mapping"""
-        self.connection.execute(
-            "INSERT OR IGNORE INTO src_file (path) VALUES (?)", (path,)
-        )
-
-    def _get_srcfile(self, path) -> int:
-        """Get a source code file id with path"""
-        srcfile_id = self.connection.execute(
-            "SELECT id FROM src_file WHERE path == ?", (path,)
-        ).fetchone()[0]
-        return srcfile_id
-
-    def _add_testfile(self, path):
-        """Add a test file to mapping"""
-        self.connection.execute(
-            "INSERT OR IGNORE INTO test_file (path) VALUES (?)", (path,)
-        )
-
-    def _get_testfile(self, path) -> int:
-        """Get a test code file id with path"""
-        testfile_id = self.connection.execute(
-            "SELECT id FROM test_file WHERE path == ?", (path,)
-        ).fetchone()[0]
-        return testfile_id
-
-    def _add_test_function(self, test_function_data):
-        """Add a test function to mapping"""
-        self.connection.execute(
-            """INSERT OR IGNORE
-                INTO test_function
-                (test_file_id,context,start,end,duration)
-                VALUES (?,?,?,?,?)""",
-            (
-                test_function_data.testfile_id,
-                test_function_data.testname,
-                test_function_data.start_line_number,
-                test_function_data.end_line_number,
-                test_function_data.elapsed_time,
-            ),
-        )
-
-    def _get_test_function(self, testname) -> int:
-        """Get a test function id with test name"""
-        test_function_id = self.connection.execute(
-            "SELECT id FROM test_function WHERE context == ?", (testname,)
-        ).fetchone()[0]
-        return test_function_id
-
-    def set_last_update_hash(self, commithash):
-        """Set the latest database update Git commit hash"""
-        self.connection.execute("DELETE FROM last_update_hash")
-        self.connection.execute(
-            "INSERT INTO last_update_hash VALUES (?)", (commithash,)
-        )
-
-    def init_mapping(self):
-        """Create the mapping database tables"""
-        self.connection.execute(
-            """CREATE TABLE IF NOT EXISTS test_map (
-                    file_id INTEGER,
-                    test_function_id INTEGER,
-                    line_id INTEGER,
-                    UNIQUE(file_id,test_function_id,line_id))"""
-        )
-        self.connection.execute(
-            "CREATE TABLE IF NOT EXISTS src_file (id INTEGER PRIMARY KEY, path TEXT, UNIQUE (path))"
-        )
-        self.connection.execute(
-            """CREATE TABLE IF NOT EXISTS test_file (
-                id INTEGER PRIMARY KEY,
-                path TEXT,
-                UNIQUE (path))"""
-        )
-        self.connection.execute(
-            """CREATE TABLE IF NOT EXISTS test_function (
-                                    id INTEGER PRIMARY KEY,
-                                    test_file_id INTEGER,
-                                    context TEXT,
-                                    start INTEGER,
-                                    end INTEGER,
-                                    duration REAL,
-                                    FOREIGN KEY (test_file_id) REFERENCES test_file(id),
-                                    UNIQUE (context))"""
-        )
-        self.connection.execute("CREATE TABLE IF NOT EXISTS new_tests (context TEXT)")
-        self.connection.execute(
-            "CREATE TABLE IF NOT EXISTS last_update_hash (hash TEXT)"
-        )
-
-    def line_exists(self, file_id, line_number) -> bool:
-        """Check whether a specific line number is covered for a source code file"""
-        return bool(
-            self.connection.execute(
-                "SELECT EXISTS(SELECT file_id FROM test_map WHERE file_id = ? AND line_id = ?)",
-                (
-                    file_id,
-                    line_number,
-                ),
-            ).fetchone()[0]
-        )
-
-    def _update_test_function_mapping(self, line_map, file_id):
-        """Update test function entries in the mapping database
-        by shifting their start and end line numbers
-        """
-        entries_to_update = self.connection.execute(
-            """SELECT id,test_file_id,context,start,end,duration FROM test_function
-                WHERE test_file_id = ?""",
-            (file_id,),
-        ).fetchall()
-
-        self.connection.execute(
-            "DELETE FROM test_function WHERE test_file_id = ?", (file_id,)
-        )
-        updated_entries = [
-            (
-                x[0],
-                x[1],
-                x[2],
-                line_map[x[3]] if x[3] in line_map else x[3],
-                line_map[x[4]] if x[4] in line_map else x[4],
-                x[5],
-            )
-            for x in entries_to_update
-        ]
-        self.connection.executemany(
-            """
-                INSERT OR IGNORE
-                INTO test_function (id,test_file_id,context,start,end,duration)
-                VALUES (?,?,?,?,?,?)""",
-            updated_entries,
-        )
-
-    def _update_line_mapping(self, line_map, file_id):
-        """Update source code mapping
-        by changing the covered line numbers
-        according to a new line mapping
-        """
-        lines = list(line_map.keys())
-        sql_params = tuple(lines + ([file_id]))
-
-        entries_to_update = self.connection.execute(
-            f"""SELECT file_id,test_function_id,line_id
-                FROM test_map WHERE line_id IN ({','.join(['?']*len(lines))}) AND file_id == ?""",
-            sql_params,
-        ).fetchall()
-
-        self.connection.execute(
-            f"""DELETE FROM test_map
-            WHERE line_id IN ({','.join(['?']*len(lines))}) AND file_id == ?""",
-            sql_params,
-        )
-        updated_entries = [(x[0], x[1], line_map[x[2]]) for x in entries_to_update]
-        self.connection.executemany(
-            "INSERT OR IGNORE INTO test_map (file_id,test_function_id,line_id) VALUES (?,?,?)",
-            updated_entries,
-        )
-
-    def save_testrun_data(
-        self,
-        testrun_data,
-    ):
-        """Save the coverage information of running a single test function"""
-        testfile_path = os.path.relpath(testrun_data.pytest_item.location[0])
-
-        self._add_testfile(testfile_path)
-        testfile_id = self._get_testfile(testfile_path)
-
-        testname = testrun_data.pytest_item.nodeid
-        test_function_name = testrun_data.pytest_item.originalname
-
-        test_function_data = TestFunctionData(
-            testfile_id=testfile_id,
-            testname=testname,
-            start_line_number=testrun_data.test_function_lines[testfile_path][
-                test_function_name
-            ][0],
-            end_line_number=testrun_data.test_function_lines[testfile_path][
-                test_function_name
-            ][1],
-            elapsed_time=testrun_data.elapsed_time,
-        )
-
-        self._add_test_function(test_function_data)
-        test_function_id = self._get_test_function(testname)
-
-        for filename in testrun_data.coverage_data.measured_files():
-            src_file_path = os.path.relpath(filename, os.getcwd())
-            # issue: find a way to get rid of hardcoded mapping conditions
-            conditions = [
-                "pytest-rts" in filename,
-                ("/tmp/" in filename) and ("/tmp/" not in os.getcwd()),
-                "/.venv/" in filename,
-                src_file_path in testrun_data.found_testfiles,
-                src_file_path.endswith("conftest.py"),
-                not src_file_path.endswith(".py"),
-            ]
-            if any(conditions):
-                continue
-
-            self._add_srcfile(src_file_path)
-            src_id = self._get_srcfile(src_file_path)
-            self._add_lines(
-                src_id, test_function_id, testrun_data.coverage_data.lines(filename)
-            )
-
-    def update_mapping(self, update_data):
-        """Remove old data from database and shift existing lines if needed"""
-
-        line_map_test = update_data.new_line_map_test
-        changed_lines_src = update_data.changed_lines_src
-        line_map_src = update_data.new_line_map_src
-
-        for testfile_id in line_map_test.keys():
-            # shift test functions
-            self._update_test_function_mapping(line_map_test[testfile_id], testfile_id)
-        for srcfile_id in changed_lines_src.keys():
-            # delete ran lines of src file mapping to be remapped by coverage collection
-            # shift affected lines by correct amount
-            self._delete_lines(changed_lines_src[srcfile_id], srcfile_id)
-            self._update_line_mapping(line_map_src[srcfile_id], srcfile_id)
diff --git a/pytest_rts/utils/selection.py b/pytest_rts/utils/selection.py
deleted file mode 100644
index b75b311..0000000
--- a/pytest_rts/utils/selection.py
+++ /dev/null
@@ -1,182 +0,0 @@
-"""This module contains code for the test selection functionality of the RTS tool"""
-from typing import Dict, List, NamedTuple, Set, Tuple
-from pytest_rts.utils.common import (
-    file_diff_dict_between_commits,
-    file_diff_dict_current,
-    run_new_test_collection,
-    split_changes,
-    tests_from_changed_srcfiles,
-    tests_from_changed_testfiles,
-)
-from pytest_rts.utils.git import (
-    changed_files_current,
-    changed_files_between_commits,
-    get_current_head_hash,
-)
-from pytest_rts.utils.mappinghelper import MappingHelper
-from pytest_rts.utils.testgetter import TestGetter
-
-
-UpdateData = NamedTuple(
-    "UpdateData",
-    [
-        ("changed_lines_test", Dict[int, List[int]]),
-        ("new_line_map_test", Dict[int, Dict[int, int]]),
-        ("changed_lines_src", Dict[int, List[int]]),
-        ("new_line_map_src", Dict[int, Dict[int, int]]),
-    ],
-)
-
-TestsAndDataFromChanges = NamedTuple(
-    "TestsAndDataFromChanges",
-    [
-        ("test_set", Set[str]),
-        ("update_data", UpdateData),
-        ("files_to_warn", List[str]),
-    ],
-)
-
-
-TestsAndDataCurrent = NamedTuple(
-    "TestsAndDataCurrent",
-    [
-        ("test_set", Set[str]),
-        ("changed_testfiles_amount", int),
-        ("changed_srcfiles_amount", int),
-    ],
-)
-
-
-TestsAndDataCommitted = NamedTuple(
-    "TestsAndDataCommitted",
-    [
-        ("test_set", Set[str]),
-        ("update_data", UpdateData),
-        ("changed_testfiles_amount", int),
-        ("changed_srcfiles_amount", int),
-        ("new_tests_amount", int),
-        ("warning_needed", bool),
-        ("files_to_warn", List[str]),
-    ],
-)
-
-TestsFromChangesInput = NamedTuple(
-    "TestsFromChangesInput",
-    [
-        ("test_file_diffs", Dict[int, str]),
-        ("src_file_diffs", Dict[int, str]),
-        ("testfiles", List[Tuple[int, str]]),
-        ("srcfiles", List[Tuple[int, str]]),
-        ("mappinghelper", MappingHelper),
-        ("testgetter", TestGetter),
-    ],
-)
-
-
-def get_tests_from_changes(tests_from_changes_input) -> TestsAndDataFromChanges:
-    """Returns the test set and data required for line shifting"""
-    (
-        src_test_set,
-        changed_lines_src,
-        new_line_map_src,
-        files_to_warn,
-    ) = tests_from_changed_srcfiles(
-        tests_from_changes_input.src_file_diffs,
-        tests_from_changes_input.srcfiles,
-        tests_from_changes_input.mappinghelper,
-        tests_from_changes_input.testgetter,
-    )
-
-    (
-        test_test_set,
-        changed_lines_test,
-        new_line_map_test,
-    ) = tests_from_changed_testfiles(
-        tests_from_changes_input.test_file_diffs,
-        tests_from_changes_input.testfiles,
-        tests_from_changes_input.testgetter,
-    )
-
-    test_set = test_test_set.union(src_test_set)
-
-    update_data = UpdateData(
-        changed_lines_test=changed_lines_test,
-        new_line_map_test=new_line_map_test,
-        changed_lines_src=changed_lines_src,
-        new_line_map_src=new_line_map_src,
-    )
-
-    return TestsAndDataFromChanges(
-        test_set=test_set, update_data=update_data, files_to_warn=files_to_warn
-    )
-
-
-def get_tests_and_data_current(mappinghelper, testgetter) -> TestsAndDataCurrent:
-    """Returns the test set from working directory changes and data for printing statistics"""
-    changed_files = changed_files_current()
-    changed_test_files, changed_src_files = split_changes(changed_files, mappinghelper)
-
-    src_file_diffs = file_diff_dict_current(changed_src_files)
-    test_file_diffs = file_diff_dict_current(changed_test_files)
-
-    tests_from_changes_input = TestsFromChangesInput(
-        test_file_diffs=test_file_diffs,
-        src_file_diffs=src_file_diffs,
-        testfiles=changed_test_files,
-        srcfiles=changed_src_files,
-        mappinghelper=mappinghelper,
-        testgetter=testgetter,
-    )
-
-    changes = get_tests_from_changes(tests_from_changes_input)
-
-    return TestsAndDataCurrent(
-        test_set=changes.test_set,
-        changed_testfiles_amount=len(changed_test_files),
-        changed_srcfiles_amount=len(changed_src_files),
-    )
-
-
-def get_tests_and_data_committed(mappinghelper, testgetter) -> TestsAndDataCommitted:
-    """Compares current git HEAD has to previous update state commit hash
-    Returns the test set and data required for line-shifting and printing statistics
-    """
-    current_hash = get_current_head_hash()
-    previous_hash = mappinghelper.last_update_hash
-
-    changed_files = changed_files_between_commits(previous_hash, current_hash)
-    changed_test_files, changed_src_files = split_changes(changed_files, mappinghelper)
-
-    src_file_diffs = file_diff_dict_between_commits(
-        changed_src_files, previous_hash, current_hash
-    )
-    test_file_diffs = file_diff_dict_between_commits(
-        changed_test_files, previous_hash, current_hash
-    )
-
-    run_new_test_collection()
-    new_tests = testgetter.newly_added_tests
-
-    tests_from_changes_input = TestsFromChangesInput(
-        test_file_diffs=test_file_diffs,
-        src_file_diffs=src_file_diffs,
-        testfiles=changed_test_files,
-        srcfiles=changed_src_files,
-        mappinghelper=mappinghelper,
-        testgetter=testgetter,
-    )
-
-    changes = get_tests_from_changes(tests_from_changes_input)
-    full_test_set = changes.test_set.union(new_tests)
-
-    warning_needed = bool(changes.files_to_warn and not new_tests)
-
-    return TestsAndDataCommitted(
-        test_set=full_test_set,
-        update_data=changes.update_data,
-        changed_testfiles_amount=len(changed_test_files),
-        changed_srcfiles_amount=len(changed_src_files),
-        new_tests_amount=len(new_tests),
-        warning_needed=warning_needed,
-        files_to_warn=changes.files_to_warn,
-    )
diff --git a/pytest_rts/utils/testgetter.py b/pytest_rts/utils/testgetter.py
deleted file mode 100644
index c6848c5..0000000
--- a/pytest_rts/utils/testgetter.py
+++ /dev/null
@@ -1,82 +0,0 @@
-"""Module for TestGetter class"""
-from typing import Dict, List, Set
-
-
-class TestGetter:
-    """Class to query tests and information from the mapping database"""
-
-    def __init__(self, connection):
-        """Set the connection"""
-        self.connection = connection
-
-    @property
-    def existing_tests(self) -> Set[str]:
-        """Test function names that exist in the mapping database"""
-        return {
-            x[0]
-            for x in self.connection.execute(
-                "SELECT context FROM test_function"
-            ).fetchall()
-        }
-
-    @property
-    def newly_added_tests(self) -> Set[str]:
-        """New tests collected but not yet mapped"""
-        return {
-            x[0]
-            for x in self.connection.execute("SELECT context FROM new_tests").fetchall()
-        }
-
-    @property
-    def test_function_runtimes(self) -> Dict[str, float]:
-        """Dictionary with saved runtimes for each test function"""
-        return {
-            x[0]: x[1]
-            for x in self.connection.execute(
-                "SELECT context, duration FROM test_function"
-            ).fetchall()
-        }
-
-    def get_tests_from_srcfiles(self, changed_lines, file_id) -> List[str]:
-        """Query tests from source code files based on changed line numbers"""
-        return [
-            line[0]
-            for line in self.connection.execute(
-                f""" SELECT DISTINCT context
-                    FROM test_function
-                    JOIN test_map ON test_function.id == test_map.test_function_id
-                    WHERE test_map.line_id IN ({','.join(['?']*len(changed_lines))})
-                    AND test_map.file_id = ?  """,
-                changed_lines + [file_id],
-            )
-        ]
-
-    def get_tests_from_testfiles(self, changed_lines, file_id) -> List[str]:
-        """Query tests from changed test code files based on changed line numbers"""
-        tests = []
-        for line_number in changed_lines:
-            tests.extend(
-                [
-                    line[0]
-                    for line in self.connection.execute(
-                        """ SELECT DISTINCT context
-                            FROM test_function
-                            WHERE test_file_id = ?
-                            AND start <= ?
-                            AND end >= ?""",
-                        (file_id, line_number, line_number),
-                    )
-                ]
-            )
-
-        return tests
-
-    def set_newly_added_tests(self, test_set):
-        """Store the newly added and collected tests"""
-        self.connection.executemany(
-            "INSERT INTO new_tests (context) VALUES (?)", [(test,) for test in test_set]
-        )
-
-    def delete_newly_added_tests(self):
-        """Clear the new tests table"""
-        self.connection.execute("DELETE FROM new_tests")