-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
25 changed files
with
675 additions
and
3 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
success,error,message | ||
True,False,Example test passed. | ||
True,False,Example test passed. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
<html><head><title>Test Results</title></head><body><table border='1'><tr><th>Success</th><th>Error</th><th>Message</th></tr><tr><td>True</td><td>False</td><td>Example test passed.</td></tr><tr><td>True</td><td>False</td><td>Example test passed.</td></tr></table></body></html> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
- error: false | ||
message: Example test passed. | ||
success: true | ||
type: example | ||
type_test: example | ||
url: http://example.com | ||
- error: false | ||
message: Example test passed. | ||
success: true | ||
type: example | ||
type_test: example | ||
url: http://another.com/another |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,70 @@ | ||
Yaml for tests will look like | ||
|
||
```yaml | ||
- url: "http://example.com" | ||
type: "example" | ||
options: | ||
param1: "value1" | ||
param2: "value2" | ||
- url: "http://another.com" | ||
type: "another_test" | ||
options: | ||
paramA: "valueA" | ||
``` | ||
where `url` is the URL to test, `type` is the test type, and `options` are the test parameters. | ||
|
||
## Testing base class | ||
|
||
The TestBase is a dataclass that holds the test data. It has the following fields: | ||
|
||
- `url` - the URL to test | ||
- `type` - the test type | ||
- `options` - the test parameters | ||
- `result` - the test result | ||
- `success`: boolean, whether the test was successful | ||
- `message`: string, a message describing the test result, this can also be the error message | ||
- `error`: boolean, whether the test failed due to an error | ||
|
||
## flow of sema-check | ||
|
||
```mermaid | ||
graph TD | ||
A[User] -->|Invokes CLI| B["CLI Module (__main__.py)"] | ||
B --> C["Argument Parser"] | ||
C --> D["Service Module (service.py)"] | ||
D --> E["Load YAML Files"] | ||
D --> F["Instantiate Test Classes"] | ||
F --> G["Test Classes (tests/)"] | ||
G --> H["Execute Tests"] | ||
H --> I["Collect Test Results"] | ||
I --> J["Sink Modules (sinks/)"] | ||
J --> K["CSV Sink (csv_sink.py)"] | ||
J --> L["HTML Sink (html_sink.py)"] | ||
J --> M["YML Sink (yml_sink.py)"] | ||
K --> N["Output: results.csv"] | ||
L --> O["Output: results.html"] | ||
M --> P["Output: results.yml"] | ||
D --> Q["Utilities (utils.py)"] | ||
Q --> R["Utility Functions"] | ||
%% Styling Nodes | ||
style A fill:#f9f,stroke:#333,stroke-width:2px | ||
style B fill:#bbf,stroke:#333,stroke-width:2px | ||
style C fill:#bbf,stroke:#333,stroke-width:2px | ||
style D fill:#bbf,stroke:#333,stroke-width:2px | ||
style E fill:#bfb,stroke:#333,stroke-width:2px | ||
style F fill:#bfb,stroke:#333,stroke-width:2px | ||
style G fill:#fbf,stroke:#333,stroke-width:2px | ||
style H fill:#fbf,stroke:#333,stroke-width:2px | ||
style I fill:#fbb,stroke:#333,stroke-width:2px | ||
style J fill:#ffb,stroke:#333,stroke-width:2px | ||
style K fill:#bff,stroke:#333,stroke-width:2px | ||
style L fill:#bff,stroke:#333,stroke-width:2px | ||
style M fill:#bff,stroke:#333,stroke-width:2px | ||
style N fill:#cff,stroke:#333,stroke-width:2px | ||
style O fill:#cff,stroke:#333,stroke-width:2px | ||
style P fill:#cff,stroke:#333,stroke-width:2px | ||
style Q fill:#fdf,stroke:#333,stroke-width:2px | ||
style R fill:#dfd,stroke:#333,stroke-width:2px | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
# your_submodule/__init__.py | ||
|
||
from .service import run_tests | ||
from .testing.base import TestBase | ||
from .check import Check | ||
from .sinks.csv_sink import write_csv | ||
from .sinks.html_sink import write_html | ||
from .sinks.yml_sink import write_yml | ||
|
||
__all__ = [ | ||
"run_tests", | ||
"Check", | ||
"TestBase", | ||
"write_csv", | ||
"write_html", | ||
"write_yml", | ||
] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,72 @@ | ||
# your_submodule/__main__.py | ||
|
||
# your_submodule/cli.py | ||
import sys | ||
from logging import getLogger | ||
|
||
from sema.commons.cli import Namespace, SemaArgsParser | ||
from sema.check import Check | ||
|
||
log = getLogger(__name__) | ||
|
||
|
||
def get_arg_parser() -> SemaArgsParser: | ||
""" | ||
Defines the arguments to this script by using Python's | ||
[argparse](https://docs.python.org/3/library/argparse.html) | ||
""" | ||
parser = SemaArgsParser( | ||
"sema-check", | ||
"Run tests based on YAML configurations.", | ||
) | ||
|
||
parser.add_argument( | ||
"-i", | ||
"--input_folder", | ||
action="store", | ||
required=True, | ||
help="Path to the folder containing YAML files.", | ||
) | ||
|
||
parser.add_argument( | ||
"-o", | ||
"--output", | ||
choices=["csv", "html", "yml"], | ||
default="csv", | ||
help="Output format for the test results.", | ||
) | ||
|
||
return parser | ||
|
||
|
||
def make_service(args: Namespace) -> Check: | ||
return Check( | ||
input_folder=args.input_folder, | ||
output=args.output, | ||
) | ||
|
||
|
||
def _main(*args_list) -> bool: | ||
log.info(f"Running sema-check with args: {args_list}") | ||
args = get_arg_parser().parse_args(args_list) | ||
|
||
try: | ||
check = make_service(args) | ||
r = check.process() | ||
print(f"Finished running tests: {r}") | ||
return bool(r) | ||
except Exception as e: | ||
log.error(f"An error occurred: {e}") | ||
return False | ||
|
||
|
||
def main(args=None): | ||
log.debug(f"Running sema-check with args: {args[1:]}") | ||
success: bool = _main(*args[1:]) | ||
log.debug(f"Finished running sema-check") | ||
log.info(f"Success: {success}") | ||
# sys.exit(0 if success else 1) | ||
|
||
|
||
if __name__ == "__main__": | ||
main() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,61 @@ | ||
import logging | ||
from sema.commons.service import ServiceBase, ServiceResult, Trace | ||
from .service import run_tests | ||
from .sinks import write_csv, write_html, write_yml | ||
|
||
log = logging.getLogger(__name__) | ||
|
||
|
||
class CheckResult(ServiceResult): | ||
"""Result of the check service""" | ||
|
||
def __init__(self): | ||
self._success = False | ||
|
||
@property | ||
def success(self) -> bool: | ||
return self._success | ||
|
||
|
||
class Check(ServiceBase): | ||
"""The main class for the check service.""" | ||
|
||
def __init__(self, *, input_folder: str, output: str) -> None: | ||
"""Initialize the Check Service object | ||
:param input_folder: the folder where the files to be checked are located | ||
:type input_folder: str | ||
:param output: the output format to be used | ||
:type output: str | ||
""" | ||
self.input_folder = input_folder | ||
self.output = output | ||
|
||
log.debug( | ||
f"Check service initialized with input_folder: {input_folder}, output: {output}" | ||
) | ||
|
||
assert self.input_folder, "input_folder not provided" | ||
assert self.output, "output not provided" | ||
|
||
self._result = CheckResult() | ||
|
||
@Trace.init(Trace) | ||
def process(self) -> None: | ||
"""Process the check service""" | ||
try: | ||
results = run_tests(self.input_folder) | ||
log.debug(f"Test results: {results}") | ||
if self.output == "csv": | ||
write_csv(results, "results.csv") | ||
elif self.output == "html": | ||
write_html(results, "results.html") | ||
elif self.output == "yml": | ||
write_yml(results, "results.yml") | ||
log.debug(f"Test results written to results.{self.output}") | ||
self._result._success = True | ||
except Exception as e: | ||
log.error(f"An error occurred: {e}") | ||
return self._result._success | ||
finally: | ||
return self._result._success |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,60 @@ | ||
# your_submodule/service.py | ||
|
||
import os | ||
import yaml | ||
from .testing.base import TestBase | ||
from .testing.test_example import ExampleTest # Import concrete test classes | ||
|
||
import logging | ||
|
||
log = logging.getLogger(__name__) | ||
|
||
|
||
def load_yaml_files(input_folder): | ||
log.debug(f"Loading YAML files from {input_folder}") | ||
yaml_files = [ | ||
f | ||
for f in os.listdir(input_folder) | ||
if f.endswith(".yaml") or f.endswith(".yml") | ||
] | ||
rules = [] | ||
for file in yaml_files: | ||
log.debug(f"Loading {file}") | ||
try: | ||
with open(os.path.join(str(input_folder), file), "r") as stream: | ||
try: | ||
data = yaml.safe_load(stream) | ||
if data: | ||
rules.extend(data) | ||
except yaml.YAMLError as exc: | ||
log.error(f"Error parsing {file}: {exc}") | ||
except Exception as e: | ||
log.exception(f"Error loading {file}: {e}") | ||
log.debug(f"Loaded {len(rules)} rules") | ||
return rules | ||
|
||
|
||
def instantiate_test(rule): | ||
log.debug(f"Instantiating test from rule: {rule}") | ||
test_type = rule.get("type") | ||
log.debug(f"Test type: {test_type}") | ||
if test_type == "example": | ||
return ExampleTest( | ||
url=rule.get("url"), | ||
options=rule.get("options"), | ||
type_test=rule.get("type"), | ||
) | ||
# Add more test types here | ||
else: | ||
raise ValueError(f"Unknown test type: {test_type}") | ||
|
||
|
||
def run_tests(input_folder): | ||
rules = load_yaml_files(input_folder) | ||
log.debug(f"Loaded rules: {rules}") | ||
test_objects = [instantiate_test(rule) for rule in rules] | ||
results = [] | ||
for test in test_objects: | ||
result = test.run() | ||
results.append(result) | ||
return results |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
# your_submodule/sinks/__init__.py | ||
|
||
from .csv_sink import write_csv | ||
from .html_sink import write_html | ||
from .yml_sink import write_yml | ||
|
||
__all__ = [ | ||
"write_csv", | ||
"write_html", | ||
"write_yml", | ||
] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
# your_submodule/sinks/csv_sink.py | ||
|
||
import csv | ||
from typing import List | ||
from ..testing.base import TestBase | ||
|
||
|
||
def write_csv(results: List[TestBase], output_file: str): | ||
with open(output_file, "w", newline="") as csvfile: | ||
fieldnames = ["url", "type", "success", "error", "message"] | ||
writer = csv.DictWriter(csvfile, fieldnames=fieldnames) | ||
|
||
writer.writeheader() | ||
for result in results: | ||
writer.writerow( | ||
{ | ||
"url": result.url, | ||
"type": result.type_test, | ||
"success": result.success, | ||
"error": result.error, | ||
"message": result.message, | ||
} | ||
) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
# your_submodule/sinks/html_sink.py | ||
|
||
from typing import List | ||
from ..testing.base import TestResult | ||
|
||
|
||
def write_html(results: List[TestResult], output_file: str): | ||
html_content = "<html><head><title>Test Results</title></head><body>" | ||
html_content += "<table border='1'><tr><th>Success</th><th>Error</th><th>Message</th></tr>" | ||
for result in results: | ||
html_content += f"<tr><td>{result.success}</td><td>{result.error}</td><td>{result.message}</td></tr>" | ||
html_content += "</table></body></html>" | ||
|
||
with open(output_file, "w") as f: | ||
f.write(html_content) | ||
|
||
|
||
# In the future add some way to visualise this with graphs or something | ||
# For now this is good enough |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
# your_submodule/sinks/yml_sink.py | ||
|
||
import yaml | ||
from typing import List | ||
from ..testing.base import TestResult | ||
|
||
|
||
def write_yml(results: List[TestResult], output_file: str): | ||
with open(output_file, "w") as f: | ||
yaml.dump([result.__dict__ for result in results], f) |
Oops, something went wrong.