diff --git a/.gitignore b/.gitignore index edc0fc3..9b25345 100644 --- a/.gitignore +++ b/.gitignore @@ -124,6 +124,7 @@ celerybeat.pid .env .venv env/ +env37/ venv/ ENV/ env.bak/ diff --git a/README.md b/README.md index 27434c1..84c8bf0 100644 --- a/README.md +++ b/README.md @@ -13,12 +13,31 @@ Note: Feel free to modify this file according to the project's necessities. ## Environment setup -To install the required dependencies make sure `python3` points to a Python 3.10 or 3.11 installation and then run: +To install the required dependencies the Python version manager `pyenv` must be installed and in `$PATH`. + +To set up a Python 3.11 virtualenv to execute parts 1, 2, and 3 of the project run: ```shell -python3.8 -m venv env +deactivate || true # deactivate existing environment +pyenv install -s 3.11 +pyenv shell 3.11 +python3.11 -m venv env + source env/bin/activate -pip install -r requirements.txt +pip3.11 install -r requirements.txt +``` + +To set up Python 3.7 (last version supported by `mut.py`) to execute part 4 of the project run: + +```shell +deactivate || true # deactivate existing environment +pyenv install -s 3.7 +pyenv shell 3.7 +python3.7 -m venv env37 +source env37/bin/activate + +pip3.7 install MutPy==0.6.1 +pip3.7 install -r requirements.txt ``` ## Instrumentation (Part 1) @@ -26,7 +45,12 @@ pip install -r requirements.txt To generate the instrumented code for all the files in the benchmark run the command: ```shell -python3 ./instrument.py +# Reset Python to latest (system) version +deactivate || true +pyenv shell 3.11 +source env/bin/activate + +python3.11 ./instrument.py ``` The generated files are created in the directory `instrumented`. Each file name matches the file name of the @@ -37,7 +61,12 @@ corresponding source file in `benchmark`. To generate test cases for all files in the benchmark run the command: ```shell -python3 ./genetic.py +# Reset Python to latest (system) version +deactivate || true +pyenv shell 3.11 +source env/bin/activate + +python3.11 ./genetic.py ``` The test suite is created in the directory `tests`. One test file is generated for each file present in the @@ -46,5 +75,23 @@ The test suite is created in the directory `tests`. One test file is generated f The test suite can be then executed over the benchmark code with the command: ```shell -python3 -m unittest discover tests +# Reset Python to latest (system) version +deactivate || true +pyenv shell 3.11 +source env/bin/activate + +python3.11 -m unittest discover tests +``` + +## Mutation testing (Part 4) + +To run `mut.py` use Python 3.7 and run: + +```shell +# Reset Python to 3.7 version +deactivate || true +pyenv shell 3.7 +source env37/bin/activate + +python3.7 muttest.py ``` \ No newline at end of file diff --git a/archive.py b/archive.py index 64aefb6..9851f7f 100644 --- a/archive.py +++ b/archive.py @@ -34,8 +34,15 @@ class Archive: def build_suite(self) -> Set[instrument.Params]: return set(list(self.true_branches.values()) + list(self.false_branches.values())) + def suite_str(self): + suite = self.build_suite() + return " ".join([",".join([f'{k}={repr(v)}' for k, v in test.items()]) for test in suite]) + def consider_test(self, test_case: frozendict): - instrument.invoke(self.f_name, test_case) + try: + instrument.invoke(self.f_name, test_case) + except AssertionError: + return range_start, range_end = instrument.n_of_branches[self.f_name] @@ -47,7 +54,7 @@ class Archive: operators.distances_false[branch] == 0 and branch not in self.false_branches): self.false_branches[branch] = test_case - def satisfies_branch(self, test_case: frozendict) -> Optional[str]: + def satisfies_unseen_branch(self, test_case: frozendict) -> Optional[str]: try: instrument.invoke(self.f_name, test_case) except AssertionError: diff --git a/fuzzer.py b/fuzzer.py index 1627120..322540c 100644 --- a/fuzzer.py +++ b/fuzzer.py @@ -138,16 +138,18 @@ def crossover(chosen_test: Params, other_chosen_test: Params, arguments: List[Ar def generate_test_case(f_name: str, arguments: List[Arg], archive: Archive) -> Params: pool: List[Params] = get_pool(arguments) + attempts = 20 # attempts to generate a random test that satisfies a new branch + while True: test = sample(pool, 1)[0] - is_new = archive.satisfies_branch(test) + is_new = archive.satisfies_unseen_branch(test) - if is_new is None: + attempts -= 1 + + if is_new is None and attempts > 0: # print(f"Not new: {test}") continue - print(f"New {is_new}!: {test}") - try: invoke(f_name, test) return test # return only test cases that satisfy assertions diff --git a/genetic.py b/genetic.py index 9eba2b9..68b3c13 100644 --- a/genetic.py +++ b/genetic.py @@ -71,29 +71,18 @@ def generate(orig_name: str) -> Set[instrument.Params]: population = toolbox.population(n=NPOP) # Create statistics object - stats = tools.Statistics(lambda ind: ind.fitness.values) - stats.register("min", min) - stats.register("max", max) - - population, logbook = algorithms.eaSimple(population, toolbox, CXPROB, MUPROB, NGEN, verbose=False, stats=stats) - - print("population:\n" + - "\n".join([f"{str(p)} {compute_fitness(f_name, archive, p)[0]}" for p in population]) + - "\n") + population, _ = algorithms.eaSimple(population, toolbox, CXPROB, MUPROB, NGEN, verbose=False) for member in population: archive.consider_test(frozendict.frozendict(member)) - for gen, record in enumerate(logbook): - print(f"Generation {gen}: min={record['min']} max={record['max']}") - tot_covered = archive.branches_covered() cov: float = (tot_covered / total_branches) * 100 branches = archive.branches_str() print(f"{orig_name}: rep #{i:02d}: Cov: {cov:02.02f}% ({tot_covered}/{total_branches} branches): {branches}") - print(archive.build_suite()) + print(archive.suite_str()) if cov > top_coverage: top_result = archive.build_suite() diff --git a/mutmuttest.py b/mutmuttest.py new file mode 100644 index 0000000..1615214 --- /dev/null +++ b/mutmuttest.py @@ -0,0 +1,61 @@ +import argparse +import os +from mutmut.__main__ import do_run, run_mutation_tests +from mutmut import mutations_by_type + +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") + + +def run_mutmut(test_path: str, source_path: str): + run_mutation_tests(config=config, progress=progress, mutations_by_file=mutations_by_file) + + do_run(None, source_path, None, None, + 'python -m unittest ' + test_path, os.path.dirname(test_path), 0.0, 0.0, + False, False, '', None, None, + None, '', True, False, False, True) + + +# def run_mutpy(test_path: str, source_path: str): +# # run_genetic([source_path], random.randint(0, 500)) +# +# argv = ['-t', source_path, '-u', test_path, '-m'] +# argv = ['-t', source_path, '-u', test_path, '-m'] +# cfg = commandline.build_parser().parse_args(args=argv) +# +# mutation_controller = commandline.build_controller(cfg) +# mutation_controller.run() +# +# # stream = os.popen(f'mut.py --target \'{source_path}\' --unit-test \'{test_path}\' -m | tee log.txt') +# # output = stream.read() +# # score = re.search('Mutation score \\[.*\\]: (\d+\.\d+)\%', output).group(1) +# # print(output, file=sys.stderr) +# # print(f"Score is: {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] + + for filename in to_test: + for i in range(10): + source_path = os.path.join(IN_SOURCE_DIR, f"{filename}.py") + test_path = os.path.join(IN_TEST_DIR, f"test_{filename}.py") + run_mutmut(test_path, source_path) + break + break + + +if __name__ == "__main__": + main() diff --git a/muttest.py b/muttest.py index a1a8a6b..5ff5653 100644 --- a/muttest.py +++ b/muttest.py @@ -1,12 +1,7 @@ import argparse import os -import random -import re -import sys - -import instrument -from genetic import run_genetic - +from mutmut.__main__ import do_run, run_mutation_tests +from mutmut import mutations_by_type from mutpy import commandline ROOT_DIR = os.path.dirname(__file__) @@ -18,7 +13,6 @@ OUT_DIR = os.path.join(ROOT_DIR, "tests") def run_mutpy(test_path: str, source_path: str): # run_genetic([source_path], random.randint(0, 500)) - argv = ['-t', source_path, '-u', test_path, '-m'] argv = ['-t', source_path, '-u', test_path, '-m'] cfg = commandline.build_parser().parse_args(args=argv) @@ -33,7 +27,7 @@ def run_mutpy(test_path: str, source_path: str): def main(): - parser = argparse.ArgumentParser(prog='muttest.py', + 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="*") @@ -50,8 +44,6 @@ def main(): source_path = os.path.join(IN_SOURCE_DIR, f"{filename}.py") test_path = os.path.join(IN_TEST_DIR, f"test_{filename}.py") run_mutpy(test_path, source_path) - break - break if __name__ == "__main__": diff --git a/requirements.txt b/requirements.txt index c184cdd..bac24a2 100644 --- a/requirements.txt +++ b/requirements.txt @@ -3,4 +3,4 @@ deap==1.4.1 astunparse==1.6.3 frozendict==2.3.8 tqdm==4.66.1 -MutPy==0.6.1 \ No newline at end of file +mutmut==2.4.4 \ No newline at end of file diff --git a/setup.cfg b/setup.cfg index 92e79d3..be8f620 100644 --- a/setup.cfg +++ b/setup.cfg @@ -1,5 +1,5 @@ [mutmut] -paths_to_mutate=benchmark/anagram_check.py +paths_to_mutate=benchmark/ backup=False -runner=python -m unittest +runner=python -m unittest discover tests tests_dir=tests/ \ No newline at end of file diff --git a/tests/output.txt b/tests/output.txt deleted file mode 100644 index d2f5e0c..0000000 --- a/tests/output.txt +++ /dev/null @@ -1,113 +0,0 @@ -anagram_check: rep #00: Cov: 87.50% (7/8 branches): 1F 1T 2F 2T 3F 3T 4F -anagram_check: rep #01: Cov: 87.50% (7/8 branches): 1F 1T 2F 2T 3F 3T 4F -anagram_check: rep #02: Cov: 100.00% (8/8 branches): 1F 1T 2F 2T 3F 3T 4F 4T -anagram_check: rep #03: Cov: 87.50% (7/8 branches): 1F 1T 2F 2T 3F 3T 4F -anagram_check: rep #04: Cov: 87.50% (7/8 branches): 1F 1T 2F 2T 3F 3T 4F -anagram_check: rep #05: Cov: 87.50% (7/8 branches): 1F 1T 2F 2T 3F 3T 4F -anagram_check: rep #06: Cov: 100.00% (8/8 branches): 1F 1T 2F 2T 3F 3T 4F 4T -anagram_check: rep #07: Cov: 100.00% (8/8 branches): 1F 1T 2F 2T 3F 3T 4F 4T -anagram_check: rep #08: Cov: 87.50% (7/8 branches): 1F 1T 2F 2T 3F 3T 4F -anagram_check: rep #09: Cov: 100.00% (8/8 branches): 1F 1T 2F 2T 3F 3T 4F 4T -cd_count: rep #00: Cov: 100.00% (14/14 branches): 1F 1T 2F 2T 3F 3T 4F 4T 5F 5T 6F 6T 7F 7T -cd_count: rep #01: Cov: 100.00% (14/14 branches): 1F 1T 2F 2T 3F 3T 4F 4T 5F 5T 6F 6T 7F 7T -cd_count: rep #02: Cov: 100.00% (14/14 branches): 1F 1T 2F 2T 3F 3T 4F 4T 5F 5T 6F 6T 7F 7T -cd_count: rep #03: Cov: 100.00% (14/14 branches): 1F 1T 2F 2T 3F 3T 4F 4T 5F 5T 6F 6T 7F 7T -cd_count: rep #04: Cov: 100.00% (14/14 branches): 1F 1T 2F 2T 3F 3T 4F 4T 5F 5T 6F 6T 7F 7T -cd_count: rep #05: Cov: 100.00% (14/14 branches): 1F 1T 2F 2T 3F 3T 4F 4T 5F 5T 6F 6T 7F 7T -cd_count: rep #06: Cov: 100.00% (14/14 branches): 1F 1T 2F 2T 3F 3T 4F 4T 5F 5T 6F 6T 7F 7T -cd_count: rep #07: Cov: 100.00% (14/14 branches): 1F 1T 2F 2T 3F 3T 4F 4T 5F 5T 6F 6T 7F 7T -cd_count: rep #08: Cov: 100.00% (14/14 branches): 1F 1T 2F 2T 3F 3T 4F 4T 5F 5T 6F 6T 7F 7T -cd_count: rep #09: Cov: 100.00% (14/14 branches): 1F 1T 2F 2T 3F 3T 4F 4T 5F 5T 6F 6T 7F 7T -check_armstrong: rep #00: Cov: 100.00% (10/10 branches): 1F 1T 2F 2T 3F 3T 4F 4T 5F 5T -check_armstrong: rep #01: Cov: 100.00% (10/10 branches): 1F 1T 2F 2T 3F 3T 4F 4T 5F 5T -check_armstrong: rep #02: Cov: 100.00% (10/10 branches): 1F 1T 2F 2T 3F 3T 4F 4T 5F 5T -check_armstrong: rep #03: Cov: 100.00% (10/10 branches): 1F 1T 2F 2T 3F 3T 4F 4T 5F 5T -check_armstrong: rep #04: Cov: 100.00% (10/10 branches): 1F 1T 2F 2T 3F 3T 4F 4T 5F 5T -check_armstrong: rep #05: Cov: 100.00% (10/10 branches): 1F 1T 2F 2T 3F 3T 4F 4T 5F 5T -check_armstrong: rep #06: Cov: 100.00% (10/10 branches): 1F 1T 2F 2T 3F 3T 4F 4T 5F 5T -check_armstrong: rep #07: Cov: 100.00% (10/10 branches): 1F 1T 2F 2T 3F 3T 4F 4T 5F 5T -check_armstrong: rep #08: Cov: 100.00% (10/10 branches): 1F 1T 2F 2T 3F 3T 4F 4T 5F 5T -check_armstrong: rep #09: Cov: 100.00% (10/10 branches): 1F 1T 2F 2T 3F 3T 4F 4T 5F 5T -decrypt: rep #00: Cov: 100.00% (2/2 branches): 2F 2T -decrypt: rep #01: Cov: 100.00% (2/2 branches): 2F 2T -decrypt: rep #02: Cov: 100.00% (2/2 branches): 2F 2T -decrypt: rep #03: Cov: 100.00% (2/2 branches): 2F 2T -decrypt: rep #04: Cov: 100.00% (2/2 branches): 2F 2T -decrypt: rep #05: Cov: 100.00% (2/2 branches): 2F 2T -decrypt: rep #06: Cov: 100.00% (2/2 branches): 2F 2T -decrypt: rep #07: Cov: 100.00% (2/2 branches): 2F 2T -decrypt: rep #08: Cov: 100.00% (2/2 branches): 2F 2T -decrypt: rep #09: Cov: 100.00% (2/2 branches): 2F 2T -encrypt: rep #00: Cov: 100.00% (2/2 branches): 1F 1T -encrypt: rep #01: Cov: 100.00% (2/2 branches): 1F 1T -encrypt: rep #02: Cov: 100.00% (2/2 branches): 1F 1T -encrypt: rep #03: Cov: 100.00% (2/2 branches): 1F 1T -encrypt: rep #04: Cov: 100.00% (2/2 branches): 1F 1T -encrypt: rep #05: Cov: 100.00% (2/2 branches): 1F 1T -encrypt: rep #06: Cov: 100.00% (2/2 branches): 1F 1T -encrypt: rep #07: Cov: 100.00% (2/2 branches): 1F 1T -encrypt: rep #08: Cov: 100.00% (2/2 branches): 1F 1T -encrypt: rep #09: Cov: 100.00% (2/2 branches): 1F 1T -exponentiation: rep #00: Cov: 62.50% (5/8 branches): 1F 1T 2F 2T 3T -exponentiation: rep #01: Cov: 62.50% (5/8 branches): 1F 1T 2F 2T 3T -exponentiation: rep #02: Cov: 62.50% (5/8 branches): 1F 1T 2F 2T 3T -exponentiation: rep #03: Cov: 62.50% (5/8 branches): 1F 1T 2F 2T 3T -exponentiation: rep #04: Cov: 62.50% (5/8 branches): 1F 1T 2F 2T 3T -exponentiation: rep #05: Cov: 62.50% (5/8 branches): 1F 1T 2F 2T 3T -exponentiation: rep #06: Cov: 62.50% (5/8 branches): 1F 1T 2F 2T 3T -exponentiation: rep #07: Cov: 62.50% (5/8 branches): 1F 1T 2F 2T 3T -exponentiation: rep #08: Cov: 62.50% (5/8 branches): 1F 1T 2F 2T 3T -gcd: rep #00: Cov: 100.00% (10/10 branches): 1F 1T 2F 2T 3F 3T 4F 4T 5F 5T -gcd: rep #01: Cov: 100.00% (10/10 branches): 1F 1T 2F 2T 3F 3T 4F 4T 5F 5T -gcd: rep #02: Cov: 100.00% (10/10 branches): 1F 1T 2F 2T 3F 3T 4F 4T 5F 5T -gcd: rep #03: Cov: 100.00% (10/10 branches): 1F 1T 2F 2T 3F 3T 4F 4T 5F 5T -gcd: rep #04: Cov: 100.00% (10/10 branches): 1F 1T 2F 2T 3F 3T 4F 4T 5F 5T -gcd: rep #05: Cov: 100.00% (10/10 branches): 1F 1T 2F 2T 3F 3T 4F 4T 5F 5T -gcd: rep #06: Cov: 100.00% (10/10 branches): 1F 1T 2F 2T 3F 3T 4F 4T 5F 5T -gcd: rep #07: Cov: 100.00% (10/10 branches): 1F 1T 2F 2T 3F 3T 4F 4T 5F 5T -gcd: rep #08: Cov: 100.00% (10/10 branches): 1F 1T 2F 2T 3F 3T 4F 4T 5F 5T -gcd: rep #09: Cov: 100.00% (10/10 branches): 1F 1T 2F 2T 3F 3T 4F 4T 5F 5T -longest_sorted_substr: rep #00: Cov: 100.00% (4/4 branches): 1F 1T 2F 2T -longest_sorted_substr: rep #01: Cov: 100.00% (4/4 branches): 1F 1T 2F 2T -longest_sorted_substr: rep #02: Cov: 100.00% (4/4 branches): 1F 1T 2F 2T -longest_sorted_substr: rep #03: Cov: 100.00% (4/4 branches): 1F 1T 2F 2T -longest_sorted_substr: rep #04: Cov: 100.00% (4/4 branches): 1F 1T 2F 2T -longest_sorted_substr: rep #05: Cov: 100.00% (4/4 branches): 1F 1T 2F 2T -longest_sorted_substr: rep #06: Cov: 100.00% (4/4 branches): 1F 1T 2F 2T -longest_sorted_substr: rep #07: Cov: 100.00% (4/4 branches): 1F 1T 2F 2T -longest_sorted_substr: rep #08: Cov: 100.00% (4/4 branches): 1F 1T 2F 2T -longest_sorted_substr: rep #09: Cov: 100.00% (4/4 branches): 1F 1T 2F 2T -rabin_karp_search: rep #00: Cov: 90.00% (9/10 branches): 1F 1T 2F 2T 3F 3T 4F 4T 5F -rabin_karp_search: rep #01: Cov: 90.00% (9/10 branches): 1F 1T 2F 2T 3F 3T 4F 4T 5F -rabin_karp_search: rep #02: Cov: 90.00% (9/10 branches): 1F 1T 2F 2T 3F 3T 4F 4T 5F -rabin_karp_search: rep #03: Cov: 90.00% (9/10 branches): 1F 1T 2F 2T 3F 3T 4F 4T 5F -rabin_karp_search: rep #04: Cov: 90.00% (9/10 branches): 1F 1T 2F 2T 3F 3T 4F 4T 5F -rabin_karp_search: rep #05: Cov: 90.00% (9/10 branches): 1F 1T 2F 2T 3F 3T 4F 4T 5F -rabin_karp_search: rep #06: Cov: 90.00% (9/10 branches): 1F 1T 2F 2T 3F 3T 4F 4T 5F -rabin_karp_search: rep #07: Cov: 90.00% (9/10 branches): 1F 1T 2F 2T 3F 3T 4F 4T 5F -rabin_karp_search: rep #08: Cov: 90.00% (9/10 branches): 1F 1T 2F 2T 3F 3T 4F 4T 5F -rabin_karp_search: rep #09: Cov: 90.00% (9/10 branches): 1F 1T 2F 2T 3F 3T 4F 4T 5F -raildecrypt: rep #00: Cov: 87.50% (14/16 branches): 5F 5T 6F 6T 7F 8F 8T 9T 10F 10T 11F 11T 12F 12T -raildecrypt: rep #01: Cov: 93.75% (15/16 branches): 5F 5T 6F 6T 7F 7T 8F 8T 9T 10F 10T 11F 11T 12F 12T -raildecrypt: rep #02: Cov: 93.75% (15/16 branches): 5F 5T 6F 6T 7F 7T 8F 8T 9T 10F 10T 11F 11T 12F 12T -raildecrypt: rep #03: Cov: 87.50% (14/16 branches): 5F 5T 6F 6T 7F 8F 8T 9T 10F 10T 11F 11T 12F 12T -raildecrypt: rep #04: Cov: 87.50% (14/16 branches): 5F 5T 6F 6T 7F 8F 8T 9T 10F 10T 11F 11T 12F 12T -raildecrypt: rep #05: Cov: 87.50% (14/16 branches): 5F 5T 6F 6T 7F 8F 8T 9T 10F 10T 11F 11T 12F 12T -raildecrypt: rep #06: Cov: 93.75% (15/16 branches): 5F 5T 6F 6T 7F 7T 8F 8T 9T 10F 10T 11F 11T 12F 12T -raildecrypt: rep #07: Cov: 93.75% (15/16 branches): 5F 5T 6F 6T 7F 7T 8F 8T 9T 10F 10T 11F 11T 12F 12T -raildecrypt: rep #08: Cov: 93.75% (15/16 branches): 5F 5T 6F 6T 7F 7T 8F 8T 9T 10F 10T 11F 11T 12F 12T -raildecrypt: rep #09: Cov: 68.75% (11/16 branches): 5T 6F 6T 8F 8T 9T 10F 10T 11F 11T 12T -railencrypt: rep #00: Cov: 100.00% (8/8 branches): 1F 1T 2F 2T 3F 3T 4F 4T -railencrypt: rep #01: Cov: 100.00% (8/8 branches): 1F 1T 2F 2T 3F 3T 4F 4T -railencrypt: rep #02: Cov: 62.50% (5/8 branches): 1T 2F 2T 4F 4T -railencrypt: rep #03: Cov: 100.00% (8/8 branches): 1F 1T 2F 2T 3F 3T 4F 4T -zeller: rep #00: Cov: 93.75% (15/16 branches): 1F 1T 2F 2T 3F 3T 4F 4T 5F 5T 6T 7F 7T 8F 8T -zeller: rep #01: Cov: 93.75% (15/16 branches): 1F 1T 2F 2T 3F 3T 4F 4T 5F 5T 6T 7F 7T 8F 8T -zeller: rep #02: Cov: 93.75% (15/16 branches): 1F 1T 2F 2T 3F 3T 4F 4T 5F 5T 6T 7F 7T 8F 8T -zeller: rep #03: Cov: 93.75% (15/16 branches): 1F 1T 2F 2T 3F 3T 4F 4T 5F 5T 6T 7F 7T 8F 8T -zeller: rep #04: Cov: 93.75% (15/16 branches): 1F 1T 2F 2T 3F 3T 4F 4T 5F 5T 6T 7F 7T 8F 8T -zeller: rep #05: Cov: 93.75% (15/16 branches): 1F 1T 2F 2T 3F 3T 4F 4T 5F 5T 6T 7F 7T 8F 8T -zeller: rep #06: Cov: 93.75% (15/16 branches): 1F 1T 2F 2T 3F 3T 4F 4T 5F 5T 6T 7F 7T 8F 8T -zeller: rep #07: Cov: 93.75% (15/16 branches): 1F 1T 2F 2T 3F 3T 4F 4T 5F 5T 6T 7F 7T 8F 8T -zeller: rep #08: Cov: 93.75% (15/16 branches): 1F 1T 2F 2T 3F 3T 4F 4T 5F 5T 6T 7F 7T 8F 8T -zeller: rep #09: Cov: 93.75% (15/16 branches): 1F 1T 2F 2T 3F 3T 4F 4T 5F 5T 6T 7F 7T 8F 8T diff --git a/tests/test_anagram_check.py b/tests/test_anagram_check.py index 8517598..f74f0d6 100644 --- a/tests/test_anagram_check.py +++ b/tests/test_anagram_check.py @@ -1,22 +1,19 @@ from unittest import TestCase from benchmark.anagram_check import anagram_check -import inspect + class Test_anagram_check(TestCase): # distances_true = {1: [0], 2: [0]} # distances_false = {1: [1], 2: [1]} def test_anagram_check_1(self): - print(f"aaaaa {inspect.getsource(anagram_check)}") - self.assertTrue(anagram_check(s1='e', s2='4') == False) - - # distances_true = {1: [1], 3: [0]} - # distances_false = {1: [0], 3: [1]} - def test_anagram_check_2(self): - print(f"aaaaa {inspect.getsource(anagram_check)}") - self.assertTrue(anagram_check(s1='|:', s2=',=U') == False) + assert anagram_check(s1='/', s2='6') == False # distances_true = {1: [1], 3: [1], 4: [0]} # distances_false = {1: [0], 3: [0], 4: [1]} + def test_anagram_check_2(self): + assert anagram_check(s1='', s2='') == True + + # distances_true = {1: [1], 3: [0]} + # distances_false = {1: [0], 3: [1]} def test_anagram_check_3(self): - print(f"aaaaa {inspect.getsource(anagram_check)}") - self.assertTrue(anagram_check(s1='', s2='') == True) + assert anagram_check(s1='md', s2='p') == False diff --git a/tests/test_caesar_cipher.py b/tests/test_caesar_cipher.py index c8e59ca..ac2c7fb 100644 --- a/tests/test_caesar_cipher.py +++ b/tests/test_caesar_cipher.py @@ -4,14 +4,14 @@ from benchmark.caesar_cipher import decrypt class Test_encrypt(TestCase): - # distances_true = {1: [16, 0, 17, 0, 0, 41, 31]} - # distances_false = {1: [0, 42, 0, 13, 52, 0, 0]} + # distances_true = {1: [0, 0, 0, 0, 40, 0, 31, 22]} + # distances_false = {1: [33, 14, 23, 29, 0, 28, 0, 0]} def test_encrypt_1(self): - assert encrypt(strng=';t:W~",', key=52) == 'oIn,SV`' + assert encrypt(strng='vclr.q7@', key=41) == '@-6