예제 #1
0
class InitPhasePlugin:
    """Class to handle mapping database initialization"""
    def __init__(self):
        """"Constructor calls database and Coverage.py initialization"""
        self.test_func_lines = {}
        self.cov = coverage.Coverage()
        self.cov._warn_unimported_source = False
        self.testfiles = set()
        self.database = DatabaseHelper()
        self.database.init_conn()
        self.database.init_mapping_db()
        self.head_hash = get_current_head_hash()
        self.database.save_last_update_hash(self.head_hash)

    def pytest_collection_modifyitems(self, session, config, items):
        """Calculate function start and end line numbers from testfiles"""
        del session, config
        for item in items:
            testfile = item.nodeid.split("::")[0]
            self.testfiles.add(testfile)
            if testfile not in self.test_func_lines:
                testfile_src_code = coverage.python.get_python_source(testfile)
                self.test_func_lines[testfile] = calculate_func_lines(
                    testfile_src_code)

    @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()
            self.cov.save()
            end = timer()
            elapsed = round(end - start, 4)
            _, test_function_id = save_testfile_and_func_data(
                item, elapsed, self.test_func_lines, self.database)
            save_mapping_data(
                test_function_id,
                self.cov.get_data(),
                self.testfiles,
                self.database,
            )
        else:
            yield
예제 #2
0
def pytest_configure(config):
    """Register RTS plugins based on state"""
    logger = logging.getLogger()
    logging.basicConfig(format="%(message)s", level=logging.INFO)

    if config.option.rts:
        if not os.path.isfile(DB_FILE_NAME):
            logger.info("No mapping database detected, starting initialization...")
            config.pluginmanager.register(InitPhasePlugin())
            return

        db_helper = DatabaseHelper()
        db_helper.init_conn()

        workdir_data = get_tests_and_data_current(db_helper)

        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))
            return

        logger.info("No WORKING DIRECTORY tests to run, checking COMMITTED changes...")

        current_hash = get_current_head_hash()
        if db_helper.is_last_update_hash(current_hash):
            pytest.exit("Database is updated to the current commit state", 0)

        previous_hash = db_helper.get_last_update_hash()
        logger.info("Comparison: %s\n", " => ".join([current_hash, previous_hash]))

        committed_data = get_tests_and_data_committed(db_helper)

        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")
        db_helper.save_last_update_hash(current_hash)

        update_mapping_db(committed_data.update_data, db_helper)

        if committed_data.test_set:
            config.pluginmanager.register(UpdatePhasePlugin(committed_data.test_set))
            return

        pytest.exit("No tests to run", 0)