Skip to content

Commit 8cabd0b

Browse files
committed
feat: libdoc, simple test and basic lib structure
1 parent cf2c696 commit 8cabd0b

File tree

7 files changed

+137
-5
lines changed

7 files changed

+137
-5
lines changed

.github/workflows/pull_request.yml

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,3 +39,12 @@ jobs:
3939

4040
- name: Build and run docker test image
4141
run: uv run inv test-app
42+
43+
- name: Create libdoc
44+
run: uv run inv docs
45+
46+
- name: Upload artifacts
47+
uses: actions/upload-artifact@v4
48+
with:
49+
name: SchemathesisLibrary-${{ matrix.python-version }}.html
50+
path: docs/SchemathesisLibrary.html

.gitignore

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,3 +14,9 @@ wheels/
1414

1515
# pytest
1616
.pytest_cache/
17+
18+
# Robot Framework
19+
atest/output
20+
21+
# VS Code
22+
.vscode/

SchemathesisLibrary/__init__.py

Lines changed: 57 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11,26 +11,79 @@
1111
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1212
# See the License for the specific language governing permissions and
1313
# limitations under the License.
14-
14+
import schemathesis
15+
from hypothesis import given, settings, HealthCheck, Phase, Verbosity
1516
from DataDriver import DataDriver # type: ignore
17+
from robot.api.deco import keyword
1618
from robot.running.model import TestCase, TestSuite # type: ignore
1719
from robot.result.model import TestSuite as ResultTestSuite # type: ignore
1820
from robot.result.model import TestCase as ResultTestCase # type: ignore
21+
from robotlibcore import DynamicCore # type: ignore
22+
from DataDriver.AbstractReaderClass import AbstractReaderClass # type: ignore
23+
from DataDriver.ReaderConfig import TestCaseData # type: ignore
1924

2025
__version__ = "0.1.0"
2126

2227

23-
class SchemathesisLibrary:
28+
class SchemathesisReader(AbstractReaderClass):
29+
def __init__(self, *, url: "str|None" = None):
30+
self.url = url
31+
32+
def get_data_from_source(
33+
self,
34+
): # This method will be called from DataDriver to get the TestCaseData list.
35+
schema = schemathesis.from_uri(self.url)
36+
all_cases = []
37+
for op in schema.get_all_operations():
38+
op_as_strategy = op.ok().as_strategy()
39+
for case in generate_examples(op_as_strategy, 10):
40+
args = {
41+
"${case}": case,
42+
}
43+
all_cases.append(
44+
TestCaseData(test_case_name=str(case.id), arguments=args)
45+
)
46+
return all_cases
47+
48+
49+
class SchemathesisLibrary(DynamicCore):
2450
ROBOT_LIBRARY_VERSION = __version__
2551
ROBOT_LISTENER_API_VERSION = 3
2652
ROBOT_LIBRARY_SCOPE = "TEST SUITE"
2753

28-
def __init__(self):
54+
def __init__(self, *, url: "str|None" = None):
2955
self.ROBOT_LIBRARY_LISTENER = self
30-
self.data_driver = DataDriver()
56+
self.data_driver = DataDriver(
57+
reader_class=SchemathesisReader(url=url), file_regex=""
58+
)
59+
DynamicCore.__init__(self, [])
3160

3261
def _start_suite(self, data: TestSuite, result: ResultTestSuite):
3362
self.data_driver._start_suite(data, result)
3463

3564
def _start_test(self, data: TestCase, result: ResultTestCase):
3665
self.data_driver._start_test(data, result)
66+
67+
@keyword
68+
def call_and_validate(self, case: schemathesis.Case) -> None:
69+
"""Validate a Schemathesis case."""
70+
case.call_and_validate()
71+
72+
73+
def generate_examples(strategy, number) -> list[schemathesis.Case]:
74+
examples = []
75+
76+
@given(strategy)
77+
@settings(
78+
database=None,
79+
max_examples=number,
80+
deadline=None,
81+
verbosity=Verbosity.quiet,
82+
phases=(Phase.generate,),
83+
suppress_health_check=list(HealthCheck),
84+
)
85+
def example_generating_inner_function(ex):
86+
examples.append(ex)
87+
88+
example_generating_inner_function()
89+
return examples

atest/test/all_cases.robot

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
*** Settings ***
2+
Library SchemathesisLibrary
3+
4+
Test Template Wrapper
5+
6+
7+
*** Test Cases ***
8+
All Tests
9+
Wrapper test_case_1
10+
11+
12+
*** Keywords ***
13+
Wrapper
14+
[Arguments] ${case}
15+
Run And Validate ${case}

pyproject.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ requires-python = ">=3.10.1"
77
dependencies = [
88
"robotframework>=7.2.2",
99
"robotframework-datadriver>=1.11.2",
10+
"robotframework-pythonlibcore>=4.4.1",
1011
"schemathesis>=3.39.16",
1112
]
1213

tasks.py

Lines changed: 38 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,10 @@
1616

1717
import requests
1818
from invoke.tasks import task
19+
from robot.libdoc import libdoc
1920

20-
ROOT = Path(__file__).parent
21+
ROOT_DIR = Path(__file__).parent
22+
ATEST_OUTPUT_DIR = ROOT_DIR / "atest" / "output"
2123
DOCKER_IMAGE = "schemathesis-library-test"
2224
DOCKER_CONTAINER = "schemathesis-library-test-app"
2325

@@ -69,3 +71,38 @@ def test_app(ctx):
6971
print(f"Connection error: {error}")
7072
if i == 299:
7173
raise RuntimeError("Test app did not start in time")
74+
75+
76+
@task
77+
def docs(ctx, version: str | None = None):
78+
"""Generate library keyword documentation.
79+
80+
Args:
81+
version: Creates keyword documentation with version
82+
suffix in the name. Documentation is moved to docs/vesions
83+
folder.
84+
"""
85+
output = ROOT_DIR / "docs" / "SchemathesisLibrary.html"
86+
libdoc("SchemathesisLibrary", str(output))
87+
if version is not None:
88+
target = (
89+
ROOT_DIR / "docs" / "versions" / f"SchemathesisLibrary-{version.replace('v', '')}.html"
90+
)
91+
output.rename(target)
92+
93+
94+
@task
95+
def atest(ctx):
96+
"""Run acceptance tests."""
97+
args = [
98+
"uv",
99+
"run",
100+
"robot",
101+
"--pythonpath",
102+
".",
103+
"--outputdir",
104+
ATEST_OUTPUT_DIR.as_posix(),
105+
"atest/test",
106+
]
107+
ATEST_OUTPUT_DIR.mkdir(parents=True, exist_ok=True)
108+
ctx.run(" ".join(args))

uv.lock

Lines changed: 11 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)