testgenie-py 0.2.1__py3-none-any.whl → 0.2.2__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)
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: testgenie-py
3
- Version: 0.2.1
3
+ Version: 0.2.2
4
4
  Summary:
5
5
  Author: cjseitz
6
6
  Author-email: charlesjseitz@gmail.com
@@ -19,6 +19,7 @@ Requires-Dist: klara (==0.6.3)
19
19
  Requires-Dist: pygraphviz (>=1.14,<2.0)
20
20
  Requires-Dist: pytest (>=8.3.5,<9.0.0)
21
21
  Requires-Dist: staticfg (>=0.9.5,<0.10.0)
22
+ Requires-Dist: tabulate (>=0.9.0,<0.10.0)
22
23
  Requires-Dist: typed-ast (==1.5.5)
23
24
  Requires-Dist: z3-solver (==4.13.3.0)
24
25
  Description-Content-Type: text/markdown
@@ -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.2.dist-info/METADATA,sha256=gqB_l7Y9ELHsTmydKcJDaTeVKbEmgNltEhL7Si0Ll18,885
65
+ testgenie_py-0.2.2.dist-info/WHEEL,sha256=fGIA9gx4Qxk2KDKeNJCbOEwSrmLtjWCwzBz351GyrPQ,88
66
+ testgenie_py-0.2.2.dist-info/entry_points.txt,sha256=OUN4GqB4zHlHWwWGjwIPbur4E_ZqQgkeeqaCLhzRZgg,47
67
+ testgenie_py-0.2.2.dist-info/RECORD,,
testgen/.coverage DELETED
Binary file
File without changes
@@ -1,146 +0,0 @@
1
- from typing import List
2
-
3
-
4
- def bin_and(a: bool, b: bool) ->bool:
5
- """
6
- >>> bin_and(True, False)
7
- False
8
-
9
- >>> bin_and(False, True)
10
- False
11
-
12
- >>> bin_and(False, False)
13
- False
14
-
15
- >>> bin_and(True, True)
16
- True
17
- """
18
- if a == True:
19
- if b == True:
20
- return True
21
- else:
22
- return False
23
- else:
24
- return False
25
-
26
-
27
- def bin_xor(a: bool, b: bool) ->bool:
28
- """
29
- >>> bin_xor(True, True)
30
- False
31
-
32
- >>> bin_xor(True, False)
33
- True
34
-
35
- >>> bin_xor(False, False)
36
- False
37
-
38
- >>> bin_xor(False, True)
39
- True
40
- """
41
- if a == True:
42
- if b == True:
43
- return False
44
- else:
45
- return True
46
- elif b == True:
47
- return True
48
- else:
49
- return False
50
-
51
-
52
- def status_flags(active: bool, verified: bool, admin: bool) ->str:
53
- """
54
- >>> status_flags(False, False, False)
55
- 'inactive'
56
-
57
- >>> status_flags(False, False, True)
58
- 'admin-unverified'
59
-
60
- >>> status_flags(True, True, False)
61
- 'user-verified'
62
-
63
- >>> status_flags(True, True, True)
64
- 'admin-verified'
65
-
66
- >>> status_flags(True, False, False)
67
- 'user-unverified'
68
-
69
- >>> status_flags(False, True, True)
70
- 'admin-verified'
71
-
72
- >>> status_flags(False, True, False)
73
- 'inactive'
74
-
75
- >>> status_flags(True, False, True)
76
- 'admin-unverified'
77
- """
78
- if admin:
79
- if verified:
80
- return 'admin-verified'
81
- else:
82
- return 'admin-unverified'
83
- elif active:
84
- if verified:
85
- return 'user-verified'
86
- else:
87
- return 'user-unverified'
88
- else:
89
- return 'inactive'
90
-
91
-
92
- """def half_adder(a: bool, b: bool) ->tuple:
93
- sum: bool = bin_xor(a, b)
94
- carry: bool = bin_and(a, b)
95
- return sum, carry
96
-
97
-
98
- def full_adder(a: bool, b: bool, carry_in: bool) ->tuple:
99
- sum1, carry = half_adder(a, b)
100
- sum2, carry_out = half_adder(sum1, carry_in)
101
- return sum2, carry or carry_out
102
-
103
-
104
- def thirty_two_bit_adder_excep(x: int, y: int) ->List[int]:
105
- x_bits: List[int] = bit_converter(x)
106
- y_bits: List[int] = bit_converter(y)
107
- result: List[int] = [0] * 32
108
- carry: bool = False
109
- for i in range(32):
110
- try:
111
- sum_bit, carry = full_adder(x_bits[i], y_bits[i], carry)
112
- result[i] = sum_bit
113
- except IndexError as e:
114
- print(f'Index Out of Bounds Error In ThirtyTwoBitAdder: {e}')
115
- result = [1] * 32
116
- if carry:
117
- return OverflowError('Sum exceeds 32 bits')
118
- return result
119
-
120
-
121
- def thirty_two_bit_adder(x: int, y: int) ->List[int]:
122
- print(x.bit_length() - 1)
123
- print(y.bit_length() - 1)
124
- x_bits: List[int] = bit_converter(x)
125
- y_bits: List[int] = bit_converter(y)
126
- result: List[int] = [0] * 32
127
- carry: bool = False
128
- for i in range(32):
129
- sum_bit, carry = full_adder(x_bits[i], y_bits[i], carry)
130
- result[i] = sum_bit
131
- return result
132
-
133
- def bit_converter(num: int) ->List[int]:
134
- binary_str: str = bin(num)[2:]
135
- print(bin(num)[2:])
136
- return [int(digit) for digit in binary_str]
137
-
138
- def thirty_two_bit_adder_excep(x: int, y: int) ->List[int]:
139
- x_bits: List[int] = bit_converter(x)
140
- y_bits: List[int] = bit_converter(y)
141
- result: List[int] = [0] * 32
142
- carry: bool = False
143
- for i in range(32):
144
- sum_bit, carry = full_adder(x_bits[i], y_bits[i], carry)
145
- result[i] = sum_bit
146
- return result"""
@@ -1,29 +0,0 @@
1
- class AdvancedCalculator:
2
-
3
- def evaluate(self, a: int, b: int, op: str) ->(int | float | str):
4
- """>>> AdvancedCalculator().evaluate(16, 56, 'abc')
5
- 'invalid'"""
6
- if op == 'add':
7
- return a + b
8
- elif op == 'sub':
9
- return a - b
10
- elif op == 'mul':
11
- return a * b
12
- elif op == 'div':
13
- if b == 0:
14
- return 'undefined'
15
- return a / b
16
- else:
17
- return 'invalid'
18
-
19
- def is_in_range(self, val: float) ->str:
20
- """>>> AdvancedCalculator().is_in_range(0.4023417704905361)
21
- 'fractional'"""
22
- if val < 0.0:
23
- return 'below zero'
24
- elif 0.0 <= val < 1.0:
25
- return 'fractional'
26
- elif 1.0 <= val <= 100.0:
27
- return 'valid'
28
- else:
29
- return 'out of range'