import argparse import os import re from collections import defaultdict import pandas as pd from tqdm import tqdm from mutpy import commandline import sys from io import StringIO import contextlib import subprocess from typing import List, Dict, DefaultDict ROOT_DIR = os.path.dirname(__file__) IN_SOURCE_DIR = os.path.join(ROOT_DIR, "benchmark") IN_TEST_DIR = os.path.join(ROOT_DIR, "tests") OUT_DIR = os.path.join(ROOT_DIR, "tests") MUT_PY_PATH = os.path.join(ROOT_DIR, 'env37', 'bin', 'mut.py') REPS: int = 10 class OutputCapture(): result: str @contextlib.contextmanager def capture_stdout(): old = sys.stdout capturer = StringIO() sys.stdout = capturer data = OutputCapture() yield data sys.stdout = old data.result = capturer.getvalue() def run_mutpy(test_path: str, source_path: str) -> float: output = subprocess.check_output( [sys.executable, MUT_PY_PATH, '-t', source_path, '-u', test_path]).decode('utf-8') score = re.search('Mutation score \\[.*]: (\\d+\\.\\d+)%', output).group(1) return float(score) def main(): parser = argparse.ArgumentParser(prog='mutmuttest.py', description='Runs MutPy over generated test suite.') parser.add_argument('file', type=str, help="Source file to test", nargs="*") files = parser.parse_args().file if len(files) == 0: files = [os.path.splitext(f) for f in os.listdir(IN_SOURCE_DIR)] to_test = [file[0] for file in files if file[1] == ".py"] else: to_test = [os.path.splitext(os.path.basename(file))[0] for file in files] scores: List[Dict[str, any]] = [] to_test = [e for t in to_test for e in ([t] * REPS)] for filename in tqdm(to_test, desc="Running mut.py over test suite"): source_path = os.path.join(IN_SOURCE_DIR, f"{filename}.py") test_path = os.path.join(IN_TEST_DIR, f"test_{filename}.py") scores.append({ 'file': filename, 'score': run_mutpy(test_path, source_path) }) df = pd.DataFrame.from_records(scores) df.to_csv(os.path.join(OUT_DIR, 'mutation_results.csv')) if __name__ == "__main__": main()