jevtest 0.5.0__tar.gz
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.
- jevtest-0.5.0/LICENSE +21 -0
- jevtest-0.5.0/PKG-INFO +135 -0
- jevtest-0.5.0/README.md +89 -0
- jevtest-0.5.0/jevtest/__init__.py +3 -0
- jevtest-0.5.0/jevtest/__main__.py +7 -0
- jevtest-0.5.0/jevtest/adapters/__init__.py +4 -0
- jevtest-0.5.0/jevtest/adapters/clock.py +17 -0
- jevtest-0.5.0/jevtest/adapters/devices/__init__.py +1 -0
- jevtest-0.5.0/jevtest/adapters/devices/android.py +556 -0
- jevtest-0.5.0/jevtest/adapters/devices/android_agent/AndroidManifest.xml +14 -0
- jevtest-0.5.0/jevtest/adapters/devices/android_agent/src/dev/jevtest/agent/Agent.java +305 -0
- jevtest-0.5.0/jevtest/adapters/devices/common.py +174 -0
- jevtest-0.5.0/jevtest/adapters/devices/ios.py +569 -0
- jevtest-0.5.0/jevtest/adapters/devices/ios_agent/AgentHost/AppDelegate.swift +18 -0
- jevtest-0.5.0/jevtest/adapters/devices/ios_agent/AgentUITests/JevAgentUITests.swift +346 -0
- jevtest-0.5.0/jevtest/adapters/devices/ios_agent/JevAgent.xcodeproj/project.pbxproj +443 -0
- jevtest-0.5.0/jevtest/adapters/devices/ios_agent/JevAgent.xcodeproj/xcshareddata/xcschemes/JevAgent.xcscheme +111 -0
- jevtest-0.5.0/jevtest/adapters/jev/__init__.py +1 -0
- jevtest-0.5.0/jevtest/adapters/jev/client.py +138 -0
- jevtest-0.5.0/jevtest/adapters/jev/lockfile.py +161 -0
- jevtest-0.5.0/jevtest/adapters/jev/wire.py +63 -0
- jevtest-0.5.0/jevtest/adapters/reports/__init__.py +1 -0
- jevtest-0.5.0/jevtest/adapters/reports/json_report.py +70 -0
- jevtest-0.5.0/jevtest/adapters/reports/junit.py +44 -0
- jevtest-0.5.0/jevtest/adapters/testfile/__init__.py +1 -0
- jevtest-0.5.0/jevtest/adapters/testfile/discovery.py +35 -0
- jevtest-0.5.0/jevtest/adapters/testfile/env.py +43 -0
- jevtest-0.5.0/jevtest/adapters/testfile/loader.py +511 -0
- jevtest-0.5.0/jevtest/application/__init__.py +1 -0
- jevtest-0.5.0/jevtest/application/brain.py +236 -0
- jevtest-0.5.0/jevtest/application/planning.py +25 -0
- jevtest-0.5.0/jevtest/application/runner.py +459 -0
- jevtest-0.5.0/jevtest/cli/__init__.py +1 -0
- jevtest-0.5.0/jevtest/cli/console.py +201 -0
- jevtest-0.5.0/jevtest/cli/main.py +83 -0
- jevtest-0.5.0/jevtest/cli/run.py +270 -0
- jevtest-0.5.0/jevtest/domain/__init__.py +4 -0
- jevtest-0.5.0/jevtest/domain/decisions.py +148 -0
- jevtest-0.5.0/jevtest/domain/failures.py +29 -0
- jevtest-0.5.0/jevtest/domain/kinds.py +53 -0
- jevtest-0.5.0/jevtest/domain/model.py +76 -0
- jevtest-0.5.0/jevtest/domain/ports.py +208 -0
- jevtest-0.5.0/jevtest/domain/results.py +122 -0
- jevtest-0.5.0/jevtest/domain/rules.py +28 -0
- jevtest-0.5.0/jevtest/domain/screen.py +128 -0
- jevtest-0.5.0/jevtest/domain/steps.py +283 -0
- jevtest-0.5.0/jevtest/domain/variables.py +26 -0
- jevtest-0.5.0/jevtest/py.typed +0 -0
- jevtest-0.5.0/jevtest.egg-info/PKG-INFO +135 -0
- jevtest-0.5.0/jevtest.egg-info/SOURCES.txt +54 -0
- jevtest-0.5.0/jevtest.egg-info/dependency_links.txt +1 -0
- jevtest-0.5.0/jevtest.egg-info/entry_points.txt +2 -0
- jevtest-0.5.0/jevtest.egg-info/requires.txt +16 -0
- jevtest-0.5.0/jevtest.egg-info/top_level.txt +1 -0
- jevtest-0.5.0/pyproject.toml +118 -0
- jevtest-0.5.0/setup.cfg +4 -0
jevtest-0.5.0/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Bret Hagen
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
jevtest-0.5.0/PKG-INFO
ADDED
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: jevtest
|
|
3
|
+
Version: 0.5.0
|
|
4
|
+
Summary: Plain-English end-to-end tests for Android and iOS apps, driven by TypeSafe's Jev model
|
|
5
|
+
Author: Bret Hagen
|
|
6
|
+
License-Expression: MIT
|
|
7
|
+
Project-URL: Homepage, https://just-betr.github.io/jevtest/
|
|
8
|
+
Project-URL: Documentation, https://just-betr.github.io/jevtest/
|
|
9
|
+
Project-URL: Source, https://github.com/Just-Betr/jevtest
|
|
10
|
+
Project-URL: Issues, https://github.com/Just-Betr/jevtest/issues
|
|
11
|
+
Project-URL: Changelog, https://github.com/Just-Betr/jevtest/blob/main/CHANGELOG.md
|
|
12
|
+
Keywords: testing,e2e,mobile,android,ios,flutter,react-native,webview,ai,jev,xcuitest,uiautomator
|
|
13
|
+
Classifier: Development Status :: 4 - Beta
|
|
14
|
+
Classifier: Typing :: Typed
|
|
15
|
+
Classifier: Environment :: Console
|
|
16
|
+
Classifier: Intended Audience :: Developers
|
|
17
|
+
Classifier: Operating System :: MacOS
|
|
18
|
+
Classifier: Operating System :: POSIX :: Linux
|
|
19
|
+
Classifier: Programming Language :: Python :: 3
|
|
20
|
+
Classifier: Programming Language :: Python :: 3 :: Only
|
|
21
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
22
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
23
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
24
|
+
Classifier: Programming Language :: Python :: 3.14
|
|
25
|
+
Classifier: Topic :: Software Development :: Quality Assurance
|
|
26
|
+
Classifier: Topic :: Software Development :: Testing
|
|
27
|
+
Classifier: Topic :: Software Development :: Testing :: Acceptance
|
|
28
|
+
Requires-Python: >=3.11
|
|
29
|
+
Description-Content-Type: text/markdown
|
|
30
|
+
License-File: LICENSE
|
|
31
|
+
Requires-Dist: pyyaml>=6
|
|
32
|
+
Provides-Extra: dev
|
|
33
|
+
Requires-Dist: pytest>=8; extra == "dev"
|
|
34
|
+
Requires-Dist: pytest-cov>=5; extra == "dev"
|
|
35
|
+
Requires-Dist: ruff>=0.6; extra == "dev"
|
|
36
|
+
Requires-Dist: mypy>=1.11; extra == "dev"
|
|
37
|
+
Requires-Dist: types-PyYAML; extra == "dev"
|
|
38
|
+
Requires-Dist: import-linter>=2.1; extra == "dev"
|
|
39
|
+
Requires-Dist: build; extra == "dev"
|
|
40
|
+
Requires-Dist: pre-commit; extra == "dev"
|
|
41
|
+
Provides-Extra: docs
|
|
42
|
+
Requires-Dist: mkdocs<2,>=1.6; extra == "docs"
|
|
43
|
+
Requires-Dist: mkdocs-material>=9.5; extra == "docs"
|
|
44
|
+
Requires-Dist: mkdocstrings[python]>=0.26; extra == "docs"
|
|
45
|
+
Dynamic: license-file
|
|
46
|
+
|
|
47
|
+
<h1 align="center">jevtest</h1>
|
|
48
|
+
|
|
49
|
+
<p align="center"><b>Plain-English end-to-end tests for Android and iOS apps.</b><br>
|
|
50
|
+
Write what a user does and what they should see. Jev works out the taps. CI replays every run exactly.</p>
|
|
51
|
+
|
|
52
|
+
<p align="center">
|
|
53
|
+
<a href="https://github.com/Just-Betr/jevtest/actions/workflows/ci.yml"><img alt="CI" src="https://github.com/Just-Betr/jevtest/actions/workflows/ci.yml/badge.svg"></a>
|
|
54
|
+
<a href="https://just-betr.github.io/jevtest/contributing/"><img alt="Coverage" src="https://img.shields.io/endpoint?url=https%3A%2F%2Fjust-betr.github.io%2Fjevtest%2Fbadges%2Fcoverage.json"></a>
|
|
55
|
+
<a href="https://pypi.org/project/jevtest/"><img alt="PyPI" src="https://img.shields.io/pypi/v/jevtest"></a>
|
|
56
|
+
<a href="https://pypi.org/project/jevtest/"><img alt="Python" src="https://img.shields.io/pypi/pyversions/jevtest"></a>
|
|
57
|
+
<a href="https://just-betr.github.io/jevtest/"><img alt="Docs" src="https://img.shields.io/badge/docs-just--betr.github.io%2Fjevtest-5e35b1"></a>
|
|
58
|
+
<a href="https://github.com/Just-Betr/jevtest/blob/main/LICENSE"><img alt="MIT license" src="https://img.shields.io/badge/license-MIT-blue"></a>
|
|
59
|
+
</p>
|
|
60
|
+
|
|
61
|
+
<p align="center"><a href="https://just-betr.github.io/jevtest/"><b>Documentation</b></a> ·
|
|
62
|
+
<a href="https://just-betr.github.io/jevtest/getting-started/">Getting started</a> ·
|
|
63
|
+
<a href="https://just-betr.github.io/jevtest/reference/steps/">Steps</a> ·
|
|
64
|
+
<a href="https://just-betr.github.io/jevtest/guides/ci/">CI</a></p>
|
|
65
|
+
|
|
66
|
+
---
|
|
67
|
+
|
|
68
|
+
```yaml
|
|
69
|
+
app: build/app-debug.apk
|
|
70
|
+
device: { android: emulator-5554 }
|
|
71
|
+
|
|
72
|
+
tests:
|
|
73
|
+
- name: Sign in
|
|
74
|
+
fresh: true
|
|
75
|
+
steps:
|
|
76
|
+
- do: Sign in with email "${DEMO_EMAIL}" and password "${DEMO_PASSWORD}"
|
|
77
|
+
expect: The home screen is showing
|
|
78
|
+
see: Welcome, ${DEMO_EMAIL}
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
```console
|
|
82
|
+
$ jevtest run login.yaml --lock frozen --out results
|
|
83
|
+
jevtest 0.5.0 · android · emulator-5554 · dev.jevtest.jevtest_demo · typesafe/jev-1.13 · lockfile: frozen
|
|
84
|
+
|
|
85
|
+
▶ Sign in
|
|
86
|
+
✓ do: Sign in with email "${DEMO_EMAIL}" and password "${DEMO_PASSWORD}" (2.6s) — 3 action(s)
|
|
87
|
+
→ type "${DEMO_EMAIL}" into text_field 'Email' (confidence 0.83)
|
|
88
|
+
→ type "${DEMO_PASSWORD}" into password_field 'Password' (confidence 0.76)
|
|
89
|
+
→ tap button 'Sign in' (confidence 0.93)
|
|
90
|
+
→ done (confidence 0.96)
|
|
91
|
+
✓ expect: The home screen is showing — Jev 0.95
|
|
92
|
+
✓ see: Welcome, ${DEMO_EMAIL}
|
|
93
|
+
PASS Sign in (7.1s)
|
|
94
|
+
|
|
95
|
+
1/1 passed in 7s
|
|
96
|
+
Jev: 5 decisions, 5 from lockfile, 0 asked live in 0.0s (0% of run time), $0.0000
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
## Why jevtest
|
|
100
|
+
|
|
101
|
+
- **Tests read like the spec.** One action, then what should be true. `do:` takes a plain-English goal; `tap:`, `type:`, `swipe:`, `scroll_to:` and 20 more give exact control.
|
|
102
|
+
- **Deterministic.** Every Jev decision is recorded in a lockfile. The same screen always gets the same answer; `--lock frozen` replays a run exactly, with no network and no API key.
|
|
103
|
+
- **Nothing assumed.** No settings file, no default device, no guessing what a typo meant. The whole test file is checked before a device is touched, and every problem is reported at once with what to fix.
|
|
104
|
+
- **Real apps, real phones.** Android emulators and phones, iOS simulators and iPhones. Native, Flutter, React Native and **in-app WebViews**, driven the same way. Animations stay on, and anything a step changes on the device is put back.
|
|
105
|
+
- **No sleeps.** It waits for the screen to stop changing, reacting to the device rather than a timer.
|
|
106
|
+
- **Built for scale and CI.** `${SECRETS}` from `.env` or CI, shared test libraries, whole folders in one command, several devices at once, JUnit XML, JSON reports and failure screenshots.
|
|
107
|
+
|
|
108
|
+
## Install
|
|
109
|
+
|
|
110
|
+
```bash
|
|
111
|
+
pip install jevtest
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
You also need the platform tools for your apps: the Android SDK and a JDK, and/or Xcode. An [OpenRouter key](https://openrouter.ai/keys) gives access to Jev. See [Getting started](https://just-betr.github.io/jevtest/getting-started/).
|
|
115
|
+
|
|
116
|
+
## Run
|
|
117
|
+
|
|
118
|
+
```bash
|
|
119
|
+
jevtest run tests.yaml --lock record --out results # asks Jev about new screens, records the answers
|
|
120
|
+
jevtest run tests/ --lock frozen --out results # a whole folder, replayed exactly from the lockfiles
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
## How it works
|
|
124
|
+
|
|
125
|
+
A small agent on the device reads the accessibility tree in milliseconds. jevtest describes the screen as text and asks [Jev](https://openrouter.ai), TypeSafe's decision model, to **choose** the next action and element from the options on screen. Jev never writes free text, so everything typed comes from your test file. Each decision is recorded, acted on, and the loop repeats until the goal is done. [More](https://just-betr.github.io/jevtest/how-it-works/).
|
|
126
|
+
|
|
127
|
+
## Status
|
|
128
|
+
|
|
129
|
+
New, and tested end to end on a Flutter demo app with native and web screens: the Android emulator (API 37), a Pixel 4a (Android 13), iOS simulators (iOS 26) and an iPhone 17 (iOS 27).
|
|
130
|
+
|
|
131
|
+
Built to a high bar: a [clean architecture](https://just-betr.github.io/jevtest/architecture/) whose layer rules are checked on every commit, `mypy --strict` with no exceptions, a docstring on every public object, and unit tests covering 100% of lines and branches. Issues and pull requests are welcome; see [Contributing](https://just-betr.github.io/jevtest/contributing/).
|
|
132
|
+
|
|
133
|
+
## License
|
|
134
|
+
|
|
135
|
+
[MIT](https://github.com/Just-Betr/jevtest/blob/main/LICENSE)
|
jevtest-0.5.0/README.md
ADDED
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
<h1 align="center">jevtest</h1>
|
|
2
|
+
|
|
3
|
+
<p align="center"><b>Plain-English end-to-end tests for Android and iOS apps.</b><br>
|
|
4
|
+
Write what a user does and what they should see. Jev works out the taps. CI replays every run exactly.</p>
|
|
5
|
+
|
|
6
|
+
<p align="center">
|
|
7
|
+
<a href="https://github.com/Just-Betr/jevtest/actions/workflows/ci.yml"><img alt="CI" src="https://github.com/Just-Betr/jevtest/actions/workflows/ci.yml/badge.svg"></a>
|
|
8
|
+
<a href="https://just-betr.github.io/jevtest/contributing/"><img alt="Coverage" src="https://img.shields.io/endpoint?url=https%3A%2F%2Fjust-betr.github.io%2Fjevtest%2Fbadges%2Fcoverage.json"></a>
|
|
9
|
+
<a href="https://pypi.org/project/jevtest/"><img alt="PyPI" src="https://img.shields.io/pypi/v/jevtest"></a>
|
|
10
|
+
<a href="https://pypi.org/project/jevtest/"><img alt="Python" src="https://img.shields.io/pypi/pyversions/jevtest"></a>
|
|
11
|
+
<a href="https://just-betr.github.io/jevtest/"><img alt="Docs" src="https://img.shields.io/badge/docs-just--betr.github.io%2Fjevtest-5e35b1"></a>
|
|
12
|
+
<a href="https://github.com/Just-Betr/jevtest/blob/main/LICENSE"><img alt="MIT license" src="https://img.shields.io/badge/license-MIT-blue"></a>
|
|
13
|
+
</p>
|
|
14
|
+
|
|
15
|
+
<p align="center"><a href="https://just-betr.github.io/jevtest/"><b>Documentation</b></a> ·
|
|
16
|
+
<a href="https://just-betr.github.io/jevtest/getting-started/">Getting started</a> ·
|
|
17
|
+
<a href="https://just-betr.github.io/jevtest/reference/steps/">Steps</a> ·
|
|
18
|
+
<a href="https://just-betr.github.io/jevtest/guides/ci/">CI</a></p>
|
|
19
|
+
|
|
20
|
+
---
|
|
21
|
+
|
|
22
|
+
```yaml
|
|
23
|
+
app: build/app-debug.apk
|
|
24
|
+
device: { android: emulator-5554 }
|
|
25
|
+
|
|
26
|
+
tests:
|
|
27
|
+
- name: Sign in
|
|
28
|
+
fresh: true
|
|
29
|
+
steps:
|
|
30
|
+
- do: Sign in with email "${DEMO_EMAIL}" and password "${DEMO_PASSWORD}"
|
|
31
|
+
expect: The home screen is showing
|
|
32
|
+
see: Welcome, ${DEMO_EMAIL}
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
```console
|
|
36
|
+
$ jevtest run login.yaml --lock frozen --out results
|
|
37
|
+
jevtest 0.5.0 · android · emulator-5554 · dev.jevtest.jevtest_demo · typesafe/jev-1.13 · lockfile: frozen
|
|
38
|
+
|
|
39
|
+
▶ Sign in
|
|
40
|
+
✓ do: Sign in with email "${DEMO_EMAIL}" and password "${DEMO_PASSWORD}" (2.6s) — 3 action(s)
|
|
41
|
+
→ type "${DEMO_EMAIL}" into text_field 'Email' (confidence 0.83)
|
|
42
|
+
→ type "${DEMO_PASSWORD}" into password_field 'Password' (confidence 0.76)
|
|
43
|
+
→ tap button 'Sign in' (confidence 0.93)
|
|
44
|
+
→ done (confidence 0.96)
|
|
45
|
+
✓ expect: The home screen is showing — Jev 0.95
|
|
46
|
+
✓ see: Welcome, ${DEMO_EMAIL}
|
|
47
|
+
PASS Sign in (7.1s)
|
|
48
|
+
|
|
49
|
+
1/1 passed in 7s
|
|
50
|
+
Jev: 5 decisions, 5 from lockfile, 0 asked live in 0.0s (0% of run time), $0.0000
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
## Why jevtest
|
|
54
|
+
|
|
55
|
+
- **Tests read like the spec.** One action, then what should be true. `do:` takes a plain-English goal; `tap:`, `type:`, `swipe:`, `scroll_to:` and 20 more give exact control.
|
|
56
|
+
- **Deterministic.** Every Jev decision is recorded in a lockfile. The same screen always gets the same answer; `--lock frozen` replays a run exactly, with no network and no API key.
|
|
57
|
+
- **Nothing assumed.** No settings file, no default device, no guessing what a typo meant. The whole test file is checked before a device is touched, and every problem is reported at once with what to fix.
|
|
58
|
+
- **Real apps, real phones.** Android emulators and phones, iOS simulators and iPhones. Native, Flutter, React Native and **in-app WebViews**, driven the same way. Animations stay on, and anything a step changes on the device is put back.
|
|
59
|
+
- **No sleeps.** It waits for the screen to stop changing, reacting to the device rather than a timer.
|
|
60
|
+
- **Built for scale and CI.** `${SECRETS}` from `.env` or CI, shared test libraries, whole folders in one command, several devices at once, JUnit XML, JSON reports and failure screenshots.
|
|
61
|
+
|
|
62
|
+
## Install
|
|
63
|
+
|
|
64
|
+
```bash
|
|
65
|
+
pip install jevtest
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
You also need the platform tools for your apps: the Android SDK and a JDK, and/or Xcode. An [OpenRouter key](https://openrouter.ai/keys) gives access to Jev. See [Getting started](https://just-betr.github.io/jevtest/getting-started/).
|
|
69
|
+
|
|
70
|
+
## Run
|
|
71
|
+
|
|
72
|
+
```bash
|
|
73
|
+
jevtest run tests.yaml --lock record --out results # asks Jev about new screens, records the answers
|
|
74
|
+
jevtest run tests/ --lock frozen --out results # a whole folder, replayed exactly from the lockfiles
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
## How it works
|
|
78
|
+
|
|
79
|
+
A small agent on the device reads the accessibility tree in milliseconds. jevtest describes the screen as text and asks [Jev](https://openrouter.ai), TypeSafe's decision model, to **choose** the next action and element from the options on screen. Jev never writes free text, so everything typed comes from your test file. Each decision is recorded, acted on, and the loop repeats until the goal is done. [More](https://just-betr.github.io/jevtest/how-it-works/).
|
|
80
|
+
|
|
81
|
+
## Status
|
|
82
|
+
|
|
83
|
+
New, and tested end to end on a Flutter demo app with native and web screens: the Android emulator (API 37), a Pixel 4a (Android 13), iOS simulators (iOS 26) and an iPhone 17 (iOS 27).
|
|
84
|
+
|
|
85
|
+
Built to a high bar: a [clean architecture](https://just-betr.github.io/jevtest/architecture/) whose layer rules are checked on every commit, `mypy --strict` with no exceptions, a docstring on every public object, and unit tests covering 100% of lines and branches. Issues and pull requests are welcome; see [Contributing](https://just-betr.github.io/jevtest/contributing/).
|
|
86
|
+
|
|
87
|
+
## License
|
|
88
|
+
|
|
89
|
+
[MIT](https://github.com/Just-Betr/jevtest/blob/main/LICENSE)
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
"""Real time, for the runner's `Clock` port."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
import time
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
class SystemClock:
|
|
9
|
+
"""The system's monotonic clock."""
|
|
10
|
+
|
|
11
|
+
def now(self) -> float:
|
|
12
|
+
"""Seconds on a monotonic clock."""
|
|
13
|
+
return time.monotonic()
|
|
14
|
+
|
|
15
|
+
def sleep(self, seconds: float) -> None:
|
|
16
|
+
"""Wait."""
|
|
17
|
+
time.sleep(seconds)
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"""The device adapters: Android (adb + an on-device agent) and iOS (Xcode tools + an XCUITest agent)."""
|