testgenie-py 0.2.1__py3-none-any.whl → 0.2.3__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,12 +1,18 @@
1
+ import doctest
2
+ import importlib
1
3
  import inspect
2
4
  import json
3
5
  import os
4
6
  import re
5
7
  import sqlite3
8
+ import sys
6
9
  import time
7
10
  import subprocess
11
+ import testgen.util.coverage_utils as coverage_utils
8
12
  from types import ModuleType
9
13
  from typing import List
14
+
15
+ import testgen
10
16
  import testgen.util.file_utils as file_utils
11
17
 
12
18
  from testgen.models.test_case import TestCase
@@ -50,11 +56,6 @@ class Service:
50
56
  # Create a dummy DB service that doesn't do anything
51
57
  self.db_service = None
52
58
 
53
- def select_all_from_db(self) -> None:
54
- rows = self.db_service.get_test_suites()
55
- for row in rows:
56
- print(repr(dict(row)))
57
-
58
59
  def generate_test_cases(self) -> List[TestCase] | None:
59
60
  module = file_utils.load_module(self.file_path)
60
61
  class_name = self.analysis_service.get_class_name(module)
@@ -155,36 +156,22 @@ class Service:
155
156
 
156
157
  try:
157
158
  if self.test_format == UNITTEST_FORMAT:
158
- subprocess.run(["python", "-m", "coverage", "run", "--source=.", "-m", "unittest", test_file], check=True)
159
- result = subprocess.run(
160
- ["python", "-m", "coverage", "report", file_path_to_use],
161
- check=True,
162
- capture_output=True,
163
- text=True
164
- )
165
- coverage_output = result.stdout
159
+ self.execute_and_store_unittest(file_path_to_use, test_file)
166
160
  elif self.test_format == PYTEST_FORMAT:
167
- subprocess.run(["python", "-m", "coverage", "run", "--source=.", "-m", "pytest", test_file], check=True)
168
- result = subprocess.run(
169
- ["python", "-m", "coverage", "report", file_path_to_use],
170
- check=True,
171
- capture_output=True,
172
- text=True
173
- )
174
- coverage_output = result.stdout
161
+ self.execute_and_store_pytest(test_file)
175
162
  elif self.test_format == DOCTEST_FORMAT:
176
- result = subprocess.run(
177
- ["python", "-m", "coverage", "run", "--source=.", "-m", "doctest", "-v", test_file],
178
- check=True,
179
- capture_output=True,
180
- text=True
181
- )
182
- coverage_output = result.stdout
163
+ self.execute_and_store_doctest(test_file)
183
164
  else:
184
- raise ValueError("Unsupported test format for coverage analysis.")
185
-
165
+ raise ValueError("Unsupported test format for test results.")
166
+
167
+ #Run coverage analysis
168
+ subprocess.run(["python", "-m", "coverage", "run", "--source=.", test_file], check=True)
169
+ result = subprocess.run(["python", "-m", "coverage", "report", file_path_to_use], check=True, capture_output=True, text=True)
186
170
  self._save_coverage_data(coverage_output, file_path_to_use)
187
-
171
+ coverage_output = result.stdout
172
+
173
+ self._save_coverage_data(coverage_output, file_path_to_use)
174
+
188
175
  except subprocess.CalledProcessError as e:
189
176
  raise RuntimeError(f"Error running coverage subprocess: {e}")
190
177
 
@@ -426,4 +413,109 @@ class Service:
426
413
 
427
414
  def debug(self, message: str):
428
415
  if self.debug_mode:
429
- self.logger.debug(message)
416
+ self.logger.debug(message)
417
+
418
+ def _get_test_case_id(self, test_case_name: str) -> int:
419
+ """
420
+ Retrieve the test case ID from the database based on the test case name.
421
+ Insert the test case if it does not exist.
422
+ """
423
+ if self.db_service is None:
424
+ raise RuntimeError("Database service is not initialized.")
425
+
426
+ # Query the database for the test case ID
427
+ self.db_service.cursor.execute(
428
+ "SELECT id FROM TestCase WHERE name = ?",
429
+ (test_case_name,)
430
+ )
431
+ result = self.db_service.cursor.fetchone()
432
+
433
+ if result:
434
+ return result[0] # Return the test case ID
435
+ else:
436
+ # Insert the test case into the database
437
+ self.db_service.cursor.execute(
438
+ "INSERT INTO TestCase (name) VALUES (?)",
439
+ (test_case_name,)
440
+ )
441
+ self.db_service.conn.commit()
442
+ return self.db_service.cursor.lastrowid
443
+
444
+ def execute_and_store_pytest(self, test_file):
445
+ import pytest
446
+ from _pytest.reports import TestReport
447
+
448
+ class PytestResultPlugin:
449
+ def __init__(self, db_service, get_test_case_id):
450
+ self.db_service = db_service
451
+ self.get_test_case_id = get_test_case_id
452
+
453
+ def pytest_runtest_logreport(self, report: TestReport):
454
+ if report.when == "call":
455
+ test_case_id = self.get_test_case_id(report.nodeid)
456
+ status = report.outcome == "passed"
457
+ error_message = report.longreprtext if report.outcome == "failed" else None
458
+ self.db_service.insert_test_result(test_case_id, status, error_message)
459
+
460
+ pytest.main([test_file], plugins=[PytestResultPlugin(self.db_service, self._get_test_case_id)])
461
+
462
+ pytest.main([test_file])
463
+
464
+ def execute_and_store_unittest(self, file_path_to_use, test_file):
465
+ import unittest
466
+ loader = unittest.TestLoader()
467
+ print(f"Discovering tests in: {os.path.dirname(file_path_to_use)} with pattern: {os.path.basename(test_file)}")
468
+ test_module = os.path.relpath(test_file,
469
+ start=os.getcwd()) # Get relative path from the current working directory
470
+ test_module = test_module.replace("/", ".").replace("\\", ".").rstrip(".py") # Convert to module name
471
+ if test_module.startswith("."):
472
+ test_module = test_module[1:] # Remove leading dot if present
473
+ print(f"Test module: {test_module}")
474
+ suite = loader.loadTestsFromName(test_module)
475
+ runner = unittest.TextTestRunner()
476
+ result = runner.run(suite)
477
+
478
+ for test_case, traceback in result.failures + result.errors:
479
+ test_case_id = self._get_test_case_id(str(test_case))
480
+ self.db_service.insert_test_result(test_case_id, status=False, error=traceback)
481
+
482
+ successful_tests = set(str(test) for test in suite) - set(
483
+ str(test) for test, _ in result.failures + result.errors)
484
+ for test_case in successful_tests:
485
+ test_case_id = self._get_test_case_id(str(test_case))
486
+ self.db_service.insert_test_result(test_case_id, status=True, error=None)
487
+
488
+ def execute_and_store_doctest(self, test_file):
489
+ module_name = os.path.splitext(os.path.basename(test_file))[0]
490
+ spec = importlib.util.spec_from_file_location(module_name, test_file)
491
+ module = importlib.util.module_from_spec(spec)
492
+ sys.modules[module_name] = module
493
+ spec.loader.exec_module(module)
494
+
495
+ # Now run doctests on the loaded module
496
+ result = doctest.testmod(module)
497
+
498
+ test_case_id = self._get_test_case_id(test_file)
499
+ status = result.failed == 0
500
+ error_message = f"{result.failed} of {result.attempted} tests failed" if result.failed > 0 else None
501
+ self.db_service.insert_test_result(test_case_id, status, error_message)
502
+
503
+ def query_test_file_data(self, test_file_name: str):
504
+ if self.db_service is None:
505
+ raise RuntimeError("Database service is not initialized.")
506
+
507
+ results = self.db_service.get_test_file_data(test_file_name)
508
+ if not results:
509
+ print(f"No data found for file: {test_file_name}")
510
+ return
511
+
512
+ from tabulate import tabulate
513
+ rows = [dict(row) for row in results]
514
+
515
+ print(f"Results for file: {test_file_name}")
516
+ print(tabulate(rows, headers="keys", tablefmt="grid"))
517
+
518
+ def select_all_from_db(self) -> None:
519
+ rows = self.db_service.get_test_suites()
520
+ for row in rows:
521
+ print(repr(dict(row)))
@@ -11,7 +11,6 @@ from testgen.sqlite.db import create_database
11
11
 
12
12
  class DBService:
13
13
  def __init__(self, db_name="testgen.db"):
14
- """Initialize database service with connection to specified database."""
15
14
  self.db_name = db_name
16
15
  self.conn = None
17
16
  self.cursor = None
@@ -111,7 +110,7 @@ class DBService:
111
110
  self.conn.commit()
112
111
  return self.cursor.lastrowid
113
112
 
114
- def insert_coverage_data(self, file_name: str, executed_lines: int, missed_lines: int,
113
+ def insert_coverage_data(self, file_name: str, executed_lines: str, missed_lines: str,
115
114
  branch_coverage: float, source_file_id: int) -> int:
116
115
  """Insert coverage data and return its ID."""
117
116
  self.cursor.execute(
@@ -217,3 +216,24 @@ class DBService:
217
216
  (file_path,)
218
217
  )
219
218
  return self.cursor.fetchall()
219
+
220
+ def get_test_file_data(self, file_path: str):
221
+ """
222
+ Retrieve all test cases, coverage data, and test results for a specific file.
223
+ """
224
+ query = """
225
+ SELECT
226
+ tc.id AS test_case_id,
227
+ tc.name AS test_case_name,
228
+ tc.test_function AS test_case_test_function,
229
+ tc.test_method_type AS test_case_method_type,
230
+ COALESCE(cd.missed_lines, 'None') AS coverage_data_missed_lines
231
+ FROM SourceFile sf
232
+ LEFT JOIN Function f ON sf.id = f.source_file_id
233
+ LEFT JOIN TestCase tc ON f.id = tc.function_id
234
+ LEFT JOIN TestResult tr ON tc.id = tr.test_case_id
235
+ LEFT JOIN CoverageData cd ON sf.id = cd.source_file_id
236
+ WHERE sf.path = ?;
237
+ """
238
+ self.cursor.execute(query, (file_path,))
239
+ return self.cursor.fetchall()
@@ -3,6 +3,8 @@ from typing import List
3
3
 
4
4
  import coverage
5
5
 
6
+ from testgen.models.analysis_context import AnalysisContext
7
+ from testgen.models.function_metadata import FunctionMetadata
6
8
  from testgen.models.test_case import TestCase
7
9
  from testgen.util.file_utils import load_and_parse_file_for_tree, load_module
8
10
  from testgen.util.utils import get_function_boundaries
@@ -193,3 +195,36 @@ def get_uncovered_lines_for_func(file_name: str, class_name: str | None, func_no
193
195
  uncovered_branch_lines.append(line)
194
196
 
195
197
  return uncovered_branch_lines
198
+
199
+ def get_all_executable_statements(analysis_context: AnalysisContext, func: FunctionMetadata, test_cases):
200
+ import ast
201
+
202
+ if not test_cases:
203
+ print("Warning: No test cases available to determine executable statements")
204
+ else:
205
+ analysis = get_coverage_analysis(analysis_context.filepath, analysis_context.class_name, func.function_name, test_cases[0].inputs)
206
+
207
+ executable_lines = list(analysis[1])
208
+
209
+ with open(analysis_context.filepath, 'r') as f:
210
+ source = f.read()
211
+
212
+ tree = ast.parse(source)
213
+
214
+ for node in ast.walk(tree):
215
+ if isinstance(node, ast.FunctionDef) and node.name == func.func_def.name:
216
+ for if_node in ast.walk(node):
217
+ if isinstance(if_node, ast.If) and if_node.orelse:
218
+ if isinstance(if_node.orelse[0], ast.If):
219
+ continue
220
+ else_line = if_node.orelse[0].lineno - 1
221
+
222
+ with open(analysis_context.filepath, 'r') as f:
223
+ lines = f.readlines()
224
+ if else_line <= len(lines):
225
+ line_content = lines[else_line - 1].strip()
226
+ if line_content == "else:":
227
+ if else_line not in executable_lines:
228
+ executable_lines.append(else_line)
229
+
230
+ return sorted(executable_lines)
@@ -1,6 +1,7 @@
1
1
  import ast
2
2
  import random
3
3
  import string
4
+ from types import ModuleType
4
5
  from typing import List
5
6
 
6
7
  import testgen.util.coverage_utils
@@ -67,22 +68,38 @@ def new_random_test_case(file_name: str, class_name: str | None, func_node: ast.
67
68
  print(f"Error generating test case for {func_name}: {e}")
68
69
  raise
69
70
 
70
- # Should combining test cases preserve the parent cases or entirely replace them?
71
- def combine_cases(test_cases: List[TestCase]) -> TestCase:
72
- # TODO: Research Genetic Algorithms
73
-
71
+ def combine_cases(module: ModuleType, test_cases: List[TestCase]) -> TestCase:
72
+ """Combine two test cases by mixing their inputs and calculating the new expected output."""
73
+ if not test_cases:
74
+ raise ValueError("Cannot combine cases with empty test case list")
75
+
74
76
  random_index1 = random.randint(0, len(test_cases) - 1)
75
77
  test_case1 = test_cases[random_index1]
76
-
78
+
77
79
  test_cases_of_the_same_function = [tc for tc in test_cases if tc.func_name == test_case1.func_name]
78
- random_index2 = random.randint(0, len(test_cases) - 1)
79
-
80
- test_case2 = test_cases_of_the_same_function[random_index2]
81
-
80
+ if len(test_cases_of_the_same_function) <= 1:
81
+ return test_case1 # Not enough cases to combine
82
+
83
+ filtered_cases = [tc for tc in test_cases_of_the_same_function if tc != test_case1]
84
+ if not filtered_cases:
85
+ random_index2 = random.randint(0, len(test_cases_of_the_same_function) - 1)
86
+ test_case2 = test_cases_of_the_same_function[random_index2]
87
+ else:
88
+ test_case2 = random.choice(filtered_cases)
89
+
82
90
  mixed_inputs = mix_inputs(test_case1, test_case2)
83
-
84
- # Calculate the new expected value??
85
- return TestCase(test_case1.func_name, mixed_inputs, test_case1.expected)
91
+
92
+ try:
93
+
94
+ func = getattr(module, test_case1.func_name)
95
+
96
+ new_expected = func(*mixed_inputs)
97
+
98
+ return TestCase(test_case1.func_name, mixed_inputs, new_expected)
99
+
100
+ except Exception as e:
101
+ print(f"Error calculating expected output for combined test case: {e}")
102
+ return test_case1 if random.choice([True, False]) else test_case2
86
103
 
87
104
  def remove_case(test_cases: List[TestCase]) -> List[TestCase]:
88
105
  random_index = random.randint(0, len(test_cases) - 1)
@@ -0,0 +1,139 @@
1
+ Metadata-Version: 2.3
2
+ Name: testgenie-py
3
+ Version: 0.2.3
4
+ Summary: Automated unit test generation tool for Python.
5
+ Author: cjseitz
6
+ Author-email: charlesjseitz@gmail.com
7
+ Requires-Python: >=3.10,<4.0
8
+ Classifier: Programming Language :: Python :: 3
9
+ Classifier: Programming Language :: Python :: 3.10
10
+ Classifier: Programming Language :: Python :: 3.11
11
+ Classifier: Programming Language :: Python :: 3.12
12
+ Classifier: Programming Language :: Python :: 3.13
13
+ Requires-Dist: ConfigArgParse (==1.7)
14
+ Requires-Dist: astor (==0.8.1)
15
+ Requires-Dist: atheris (==2.3.0)
16
+ Requires-Dist: coverage (==7.6.4)
17
+ Requires-Dist: docker (>=7.1.0,<8.0.0)
18
+ Requires-Dist: klara (==0.6.3)
19
+ Requires-Dist: pygraphviz (>=1.14,<2.0)
20
+ Requires-Dist: pytest (>=8.3.5,<9.0.0)
21
+ Requires-Dist: staticfg (>=0.9.5,<0.10.0)
22
+ Requires-Dist: tabulate (>=0.9.0,<0.10.0)
23
+ Requires-Dist: typed-ast (==1.5.5)
24
+ Requires-Dist: z3-solver (==4.13.3.0)
25
+ Description-Content-Type: text/markdown
26
+
27
+ # TestGenie
28
+
29
+ **TestGenie** is an automated unit test generation tool for Python that supports multiple test generation strategies, including static AST analysis, fuzz testing, feedback-directed random testing, and reinforcement learning.
30
+ Built with a modular Pipe and Filter architecture, it analyzes Python source code to extract function metadata, generates meaningful test cases, and outputs executable test suites in formats like Unittest, PyTest, or Doctest.
31
+ The system can also measure and report code coverage and safely execute tests in Docker containers.
32
+ TestGenie aims to reduce manual testing effort, improve coverage, and explore the potential of learning-based approaches for optimizing test generation.
33
+
34
+ ---
35
+
36
+ ## Installation
37
+
38
+ Make sure you have **Python 3.10+** and **Poetry** installed.
39
+
40
+ Install dependencies:
41
+
42
+ ```bash
43
+ poetry install
44
+ ```
45
+
46
+ Activate the virtual environment:
47
+
48
+ ```bash
49
+ poetry shell
50
+ ```
51
+
52
+ ---
53
+
54
+ ## Running the CLI
55
+
56
+ To invoke the test generator, run:
57
+
58
+ ```bash
59
+ poetry run python -m testgen.main <file_path> [options]
60
+ ```
61
+
62
+ **Required Argument:**
63
+ - `<file_path>`: Path to the Python module you want to analyze.
64
+
65
+ ---
66
+
67
+ ## Command-Line Options
68
+
69
+ | Command/Flag | Description |
70
+ |:---|:---|
71
+ | `--output, -o <path>` | Path to output directory for generated test files (default: `./tests`) |
72
+ | `--generate-only, -g` | Only generate test code, skip running tests and measuring coverage |
73
+ | `--test-mode <mode>` | Set the test analysis strategy: `ast` (default), `random`, `fuzz`, or `reinforce` |
74
+ | `--test-format <format>` | Set the test output format: `unittest` (default), `pytest`, or `doctest` |
75
+ | `--safe` | Run test generation inside a Docker container for isolation and safety |
76
+ | `--query, -q` | Query the database for test cases, coverage data, and test results for a specific file |
77
+ | `--db <db_path>` | Path to SQLite database file (default: `testgen.db`) |
78
+ | `--reinforce-mode <mode>` | Set mode for reinforcement learning: `train` (default) or `collect` |
79
+ | `--visualize, -viz` | Visualize generated test coverage graphs using Graphviz |
80
+ | `--debug` | Enable debug logging output |
81
+ | `--log-file <path>` | Save logs to the specified file instead of only printing to the console |
82
+
83
+ ---
84
+
85
+ ## Examples
86
+
87
+ Generate and run unit tests for a Python module:
88
+
89
+ ```bash
90
+ poetry run python -m testgen.main mymodule.py
91
+ ```
92
+
93
+ Generate tests using fuzzing strategy and output to a custom directory:
94
+
95
+ ```bash
96
+ poetry run python -m testgen.main mymodule.py --test-mode fuzz --output generated_tests/
97
+ ```
98
+
99
+ Run reinforcement learning-based test generation:
100
+
101
+ ```bash
102
+ poetry run python -m testgen.main mymodule.py --test-mode reinforce
103
+ ```
104
+
105
+ Query previously generated test results from the database:
106
+
107
+ ```bash
108
+ poetry run python -m testgen.main mymodule.py --query
109
+ ```
110
+
111
+ Safely generate tests inside a Docker container:
112
+
113
+ ```bash
114
+ poetry run python -m testgen.main mymodule.py --safe
115
+ ```
116
+
117
+ ---
118
+
119
+ ## Features
120
+ - Static analysis using Python AST
121
+ - Fuzz testing using randomized input generation
122
+ - Feedback-directed random testing
123
+ - Reinforcement learning-based test case optimization
124
+ - Supports Unittest, PyTest, and Doctest formats
125
+ - Code coverage measurement and reporting
126
+ - Docker sandboxing for safe test execution
127
+ - SQLite database integration for tracking tests and results
128
+ - CLI visualization of test coverage graphs
129
+
130
+ ---
131
+
132
+ ## Requirements
133
+
134
+ - Python 3.10+
135
+ - Poetry
136
+ - (Optional) Docker (for safe mode execution)
137
+
138
+ ---
139
+
@@ -1,4 +1,3 @@
1
- testgen/.coverage,sha256=NvtMmi3OL9j4U8zNqffRWADmGX-9ygDEiHlCgjhbRjk,69632
2
1
  testgen/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
3
2
  testgen/analyzer/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
4
3
  testgen/analyzer/ast_analyzer.py,sha256=JmqiosxgZJm2fhNDr5VUBpKKHmf8S2HP9Jm0Xl7NnnI,6783
@@ -7,25 +6,17 @@ testgen/analyzer/contracts/contract.py,sha256=6rNYJOy_2GrOhGtaXTDIOX6pTEOqo856Fx
7
6
  testgen/analyzer/contracts/no_exception_contract.py,sha256=rTWTuu5XKmvzBPD6yNAqiNehk9lbWn_Z8zFj-_djZ_w,512
8
7
  testgen/analyzer/contracts/nonnull_contract.py,sha256=uurnrVptImYTVpSnu8ckdlU6c94AbiOWFoH1YnAQU0w,508
9
8
  testgen/analyzer/fuzz_analyzer.py,sha256=ktkDdh3mgHjcC4ZitGo9fa9RjnGqkdehaYJeSKssWss,4299
10
- testgen/analyzer/random_feedback_analyzer.py,sha256=tQkYwrYCH1xeSU5j1aoh0vUMyZwFC-1dFWf5eIlhcH8,13219
9
+ testgen/analyzer/random_feedback_analyzer.py,sha256=TCF4rBEU22YtBMBefNfuKNJRjHo5U-a6Qn-mEr1bH10,23959
11
10
  testgen/analyzer/reinforcement_analyzer.py,sha256=U6W7g-xDFS_P0aqxjPRnaXjGp2gOC9TMdfWaetFV7eE,3568
12
11
  testgen/analyzer/test_case_analyzer.py,sha256=foHRbz9K6WAn711sXbp-smJHDjI8GTG8F2TpovLZVEo,1530
13
12
  testgen/analyzer/test_case_analyzer_context.py,sha256=7umDPHBjoTaCRvZOdNynpnWsr14Gy0E2hpMBPK8mz3Q,2128
14
- testgen/code_to_test/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
15
- testgen/code_to_test/boolean.py,sha256=RM2byJDKFTx1FFrxnPG_uZWb24OcOH20Uh-D1Z-yPcE,3373
16
- testgen/code_to_test/calculator.py,sha256=j7lw21BYg_vxaQVCrjOlhQOpObjSe5gu9xzthmdGphk,830
17
- testgen/code_to_test/code_to_fuzz.py,sha256=cwgRpUdXjTlrUHSHMtA2TAj8Y-ddAn6CaUdXPM4MRmo,4826
18
- testgen/code_to_test/code_to_fuzz_lite.py,sha256=EjS4GB5klnJrvZIDDpS9iIt0iZETVJI0ez9DmihMiYc,10429
19
- testgen/code_to_test/decisions.py,sha256=ZiW-EF1yTOWeQVZ7Xh0oIPHK2NSNPUzVxCY0E2GbYvQ,1376
20
- testgen/code_to_test/math_utils.py,sha256=FqPQz5-e1oklzGyTVYNO8JMKDg5ob8z05VOlpKfKvvw,853
21
- testgen/code_to_test/no_types.py,sha256=kD8CGjVAxVeCjQC45abO773sRNIjiZ4jvhwPRV8-kt0,675
22
- testgen/code_to_test/sample_code_bin.py,sha256=kMvV_-oFeAkxUmDx41Pw0iTTmMG1pvX31TezXPWMOkE,4225
23
13
  testgen/controller/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
24
- testgen/controller/cli_controller.py,sha256=jSwT6Cy3JQhxFPRXaODdZ1md5uXO83Q0IrYh86sIdiE,8832
14
+ testgen/controller/cli_controller.py,sha256=7zDm0hPcTLQXap8Sw_s9SPYcbY0nbfvP1wW8zUqdv-8,8783
25
15
  testgen/controller/docker_controller.py,sha256=LK3aV-n_J0YMRRcWNNinz-Z0FrKo-4qzEIYZSFht0Yc,8687
26
16
  testgen/docker/Dockerfile,sha256=6mutzP0ZkVueuvMLCOy2bsyGxWjLHU-cq7RFkuC8r5Y,781
17
+ testgen/generated_samplecodebin.py,sha256=pf_aYtcfpjZzgiZ_FiBOxfug_ii3dRX0jnozBgQm7Xw,17030
27
18
  testgen/generator/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
28
- testgen/generator/code_generator.py,sha256=V5Donxz3r3ZW56xyyldJwOuDBaX6e8NOyPc8UzllQs8,2467
19
+ testgen/generator/code_generator.py,sha256=-Nh5Jt4my29YWA_LKWn98I4jvDA-fNi6AGuw-vJhRV0,3171
29
20
  testgen/generator/doctest_generator.py,sha256=Dkaf2l72ENk1mqNP3WkOnIY-iqrTHh-443AWtxzRWGY,8806
30
21
  testgen/generator/generator.py,sha256=9M9zg8DO0uU5W5s9hsz2oPCL7bz7sAD087M5TYottSs,2007
31
22
  testgen/generator/pytest_generator.py,sha256=ZjQKPHlizFK2yx9WabAxkW9sM-xa64d08IIQibnvwuk,3369
@@ -41,33 +32,28 @@ testgen/models/generator_context.py,sha256=V-T9i-3Ar-gdBzQqidyqBb05PTmOu2LtdQdAI
41
32
  testgen/models/test_case.py,sha256=jwodn-6fKHCh4SO2qycbrFyggCb9UlwTZ8k3RdTObDQ,216
42
33
  testgen/presentation/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
43
34
  testgen/presentation/cli_view.py,sha256=2fZrsvZ-Wi4j37UvogsK9_yQV5o3A20jowIr6iFRu-s,296
44
- testgen/q_table/global_q_table.json,sha256=xSMRf5ddtLJAogE_RXleAbkmujgAYU3uiblBJmKqc5w,12059
45
35
  testgen/reinforcement/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
46
36
  testgen/reinforcement/abstract_state.py,sha256=M9Kp8fyJzsTzpyL3ca4HjjYpGXy9DRMw-IG7OgFVisY,154
47
37
  testgen/reinforcement/agent.py,sha256=wvgbi-OVoVJMwhasGgsP2y1TKLiC5qjjTwZBNqKNRns,6098
48
- testgen/reinforcement/environment.py,sha256=bNsk9ejPo2ICY-FM6lwGD2W6YEuoE_N70DKazvjfrqU,10825
38
+ testgen/reinforcement/environment.py,sha256=gW-Chh_c31AXlYR5GjTKybg4iNWSuZLeujB6Q7TdKPI,10838
49
39
  testgen/reinforcement/statement_coverage_state.py,sha256=mTZ0uiFnyiIoHcQXlJv9FDSH4y1r3rxltYEdZcMaSSg,1552
50
40
  testgen/service/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
51
41
  testgen/service/analysis_service.py,sha256=LPvsb6XwFQIOn05niamDiJx_HqCyTX2UznREvKjfvWo,10973
52
42
  testgen/service/cfg_service.py,sha256=ejgwbFlwla9Mfy4OJ-hsLAxo0TV3jO06hkldeEU-akQ,2236
53
- testgen/service/generator_service.py,sha256=MOkojB4ipp-fRF0buW-rIgFJLlBaRQKzoRxyJksylao,7382
43
+ testgen/service/generator_service.py,sha256=rDwE1mGQdshr_yaDANcCPtgKhcx5sDWxQi8myxkOKhk,8088
54
44
  testgen/service/logging_service.py,sha256=vEQsluxwO-dAxWY4Xkwt8v5XeaXEv3GZh3ZYAsFCOEs,3116
55
- testgen/service/service.py,sha256=HDHm5NS_qC5EvFCcdOJAR6B3lQb8fPEmwRfZz1dV4j0,17001
45
+ testgen/service/service.py,sha256=aT6F8TxxBNLX8LIK3bVPvnohts2ssLkrr3dz-RK0L_c,20994
56
46
  testgen/sqlite/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
57
47
  testgen/sqlite/db.py,sha256=RUt88ndT4CQRo9aZzLGXPHRK1iw0LyDEGnoWlOLzKGM,2390
58
- testgen/sqlite/db_service.py,sha256=i87YkhMP0VNyug5p1tWUvnzHB8isFcSIRe9vJJTmFLA,8954
59
- testgen/testgen.db,sha256=iyQiDqur-JoS70QD-VYkJFkgjb_YcK2jBAP2aZvvAhY,106496
60
- testgen/tests/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
61
- testgen/tests/test_boolean.py,sha256=WzZPPdTLoWHEMnqopimm0g-lbJCp1ExlK_w6KN3Si1s,1636
62
- testgen/tests/test_decisions.py,sha256=NF3sTscRMHHTsaV0NzwNsQ4zW2WkPyyTp1C1Sw3rNbQ,4437
48
+ testgen/sqlite/db_service.py,sha256=F2ug_FBrYOQtJwM2cMkvQrTS54_VhWGDAHXndnTi-c8,9768
63
49
  testgen/tree/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
64
50
  testgen/tree/node.py,sha256=ONJtbACShN4yNj1X-UslFRgLyBP6mrbg7qZr3c6dWyA,165
65
51
  testgen/tree/tree_utils.py,sha256=gT7jucky6_GWVOlDI6jpv6RMeWCkntGOHIYLvHxD85k,2122
66
52
  testgen/util/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
67
- testgen/util/coverage_utils.py,sha256=Le5kC02gZewJEzzIE_Jfw17qOoPIZa9p3UTDWfwxUi0,7578
53
+ testgen/util/coverage_utils.py,sha256=xKaFpgLEZLAgDWzugxJPKVwfd0nYZnP5oHLnFzYuRPE,9084
68
54
  testgen/util/coverage_visualizer.py,sha256=Jp9d7SJaGKD38g4GWSOI4TusXtMYgMgQNPGrUnuVynk,5704
69
55
  testgen/util/file_utils.py,sha256=IO239ZQB2DoZN1URrFlPq0fv73Xn5wQUQVEWk7g4gl4,7066
70
- testgen/util/randomizer.py,sha256=J_M24XYxkPjD6wVCr8PmP_Iasc4CgwRJngxZOO6zofc,5039
56
+ testgen/util/randomizer.py,sha256=1WTPjCjgQxfHw9UPhvjRWJCKtcE3gCG4nmLn7HJtrac,5767
71
57
  testgen/util/utils.py,sha256=_TPXveAcI_TR9XLU8qaDx63CrZJDvpzSWl_gfYchJz0,5665
72
58
  testgen/util/z3_utils/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
73
59
  testgen/util/z3_utils/ast_to_z3.py,sha256=V87cvlH2OlO7_owuVTqygymMmK_FyesBovi6qe-BUcg,3180
@@ -75,7 +61,7 @@ testgen/util/z3_utils/branch_condition.py,sha256=N9FNR-iJmxIC62NpDQNVZ1OP14rXXqY
75
61
  testgen/util/z3_utils/constraint_extractor.py,sha256=RXJLpmk6dAvHZ27839VXKXNtdy9St1F-17-pSEFu4bM,1285
76
62
  testgen/util/z3_utils/variable_finder.py,sha256=dUh3F9_L_BDMz1ybiGss09LLcM_egbitgj0FT5Nh9u4,245
77
63
  testgen/util/z3_utils/z3_test_case.py,sha256=yF4oJOrXMLzOwDUqXdoeg83MOTl3pvc_lYaZcS01CuQ,4983
78
- testgenie_py-0.2.1.dist-info/METADATA,sha256=arzD3EpQ9AnK8STIuvazvbZ7Gdoj3rgzLoMVdqQ6zkg,843
79
- testgenie_py-0.2.1.dist-info/WHEEL,sha256=fGIA9gx4Qxk2KDKeNJCbOEwSrmLtjWCwzBz351GyrPQ,88
80
- testgenie_py-0.2.1.dist-info/entry_points.txt,sha256=OUN4GqB4zHlHWwWGjwIPbur4E_ZqQgkeeqaCLhzRZgg,47
81
- testgenie_py-0.2.1.dist-info/RECORD,,
64
+ testgenie_py-0.2.3.dist-info/METADATA,sha256=2-QroI89cQjovRoy2sgGDE1KiNVX4na87b-9K-35jck,4350
65
+ testgenie_py-0.2.3.dist-info/WHEEL,sha256=fGIA9gx4Qxk2KDKeNJCbOEwSrmLtjWCwzBz351GyrPQ,88
66
+ testgenie_py-0.2.3.dist-info/entry_points.txt,sha256=OUN4GqB4zHlHWwWGjwIPbur4E_ZqQgkeeqaCLhzRZgg,47
67
+ testgenie_py-0.2.3.dist-info/RECORD,,
testgen/.coverage DELETED
Binary file
File without changes