robotframework-nl 3.1.0__tar.gz → 4.0.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.
- {robotframework_nl-3.1.0/robotframework_nl.egg-info → robotframework_nl-4.0.0}/PKG-INFO +14 -40
- {robotframework_nl-3.1.0 → robotframework_nl-4.0.0}/README.md +8 -5
- {robotframework_nl-3.1.0 → robotframework_nl-4.0.0}/pyproject.toml +6 -6
- {robotframework_nl-3.1.0 → robotframework_nl-4.0.0/robotframework_nl.egg-info}/PKG-INFO +14 -40
- {robotframework_nl-3.1.0 → robotframework_nl-4.0.0}/robotnl/RobotChecks.py +81 -19
- {robotframework_nl-3.1.0 → robotframework_nl-4.0.0}/robotnl/inline_keywords.py +10 -4
- robotframework_nl-4.0.0/robotnl/version.py +1 -0
- robotframework_nl-3.1.0/robotnl/version.py +0 -1
- {robotframework_nl-3.1.0 → robotframework_nl-4.0.0}/LICENSE +0 -0
- {robotframework_nl-3.1.0 → robotframework_nl-4.0.0}/robotframework_nl.egg-info/SOURCES.txt +0 -0
- {robotframework_nl-3.1.0 → robotframework_nl-4.0.0}/robotframework_nl.egg-info/dependency_links.txt +0 -0
- {robotframework_nl-3.1.0 → robotframework_nl-4.0.0}/robotframework_nl.egg-info/requires.txt +0 -0
- {robotframework_nl-3.1.0 → robotframework_nl-4.0.0}/robotframework_nl.egg-info/top_level.txt +0 -0
- {robotframework_nl-3.1.0 → robotframework_nl-4.0.0}/robotnl/CheckOperator.py +0 -0
- {robotframework_nl-3.1.0 → robotframework_nl-4.0.0}/robotnl/__init__.py +0 -0
- {robotframework_nl-3.1.0 → robotframework_nl-4.0.0}/setup.cfg +0 -0
|
@@ -1,55 +1,26 @@
|
|
|
1
|
-
Metadata-Version: 2.
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
2
|
Name: robotframework-nl
|
|
3
|
-
Version:
|
|
4
|
-
Summary:
|
|
3
|
+
Version: 4.0.0
|
|
4
|
+
Summary: RobotNL is a proving ground to boost Robot Framework closer to Natural Language.
|
|
5
5
|
Author-email: Johan Foederer <github@famfoe.nl>
|
|
6
|
-
License: BSD
|
|
7
|
-
|
|
8
|
-
Copyright (c) 2021, J. Foederer
|
|
9
|
-
All rights reserved.
|
|
10
|
-
|
|
11
|
-
Redistribution and use in source and binary forms, with or without
|
|
12
|
-
modification, are permitted provided that the following conditions are met:
|
|
13
|
-
|
|
14
|
-
1. Redistributions of source code must retain the above copyright notice, this
|
|
15
|
-
list of conditions and the following disclaimer.
|
|
16
|
-
|
|
17
|
-
2. Redistributions in binary form must reproduce the above copyright notice,
|
|
18
|
-
this list of conditions and the following disclaimer in the documentation
|
|
19
|
-
and/or other materials provided with the distribution.
|
|
20
|
-
|
|
21
|
-
3. Neither the name of the copyright holder nor the names of its
|
|
22
|
-
contributors may be used to endorse or promote products derived from
|
|
23
|
-
this software without specific prior written permission.
|
|
24
|
-
|
|
25
|
-
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
|
26
|
-
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
27
|
-
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
|
28
|
-
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
|
29
|
-
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
30
|
-
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
|
31
|
-
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
|
32
|
-
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
|
33
|
-
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
34
|
-
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
35
|
-
|
|
6
|
+
License-Expression: BSD-3-Clause
|
|
36
7
|
Project-URL: Homepage, https://github.com/JFoederer/robotframeworkNL
|
|
37
8
|
Keywords: robotframework,robot,testing,dsl
|
|
38
|
-
Classifier: License :: OSI Approved :: BSD License
|
|
39
9
|
Classifier: Programming Language :: Python :: 3
|
|
40
10
|
Classifier: Operating System :: OS Independent
|
|
41
|
-
Requires-Python: >=3.
|
|
11
|
+
Requires-Python: >=3.14
|
|
42
12
|
Description-Content-Type: text/markdown
|
|
43
13
|
License-File: LICENSE
|
|
44
14
|
Requires-Dist: robotframework>=7.0
|
|
15
|
+
Dynamic: license-file
|
|
45
16
|
|
|
46
|
-
#
|
|
47
|
-
|
|
17
|
+
# RobotNL - the oneliner
|
|
18
|
+
RobotNL is a proving ground to boost Robot framework closer to Natural Language.
|
|
48
19
|
|
|
49
20
|
## Introduction
|
|
50
21
|
This project is an extension to [Robot framework](https://robotframework.org/) and although [Robot framework](https://robotframework.org/) made a very good step towards the goals of [keyword-driven testing ](https://en.wikipedia.org/wiki/Keyword-driven_testing) to make it readable for all stakeholders, there is still quite a lot of syntax involved that keeps test cases from really staying concise and to-the-point. In this project we will be introducing concepts to lift [Robot framework](https://robotframework.org/) to an even higher level.
|
|
51
22
|
|
|
52
|
-
This
|
|
23
|
+
This release introduces ``inline keywords`` and a set of ``Check that`` keywords that help to vastly reduce the amount of ``${...}`` cluttering in your test cases. Combining these concepts helps to write a cleaner [Domain Specific Language](https://en.wikipedia.org/wiki/Domain-specific_language) around your [domain vocabulary](https://en.wikipedia.org/wiki/Jargon).
|
|
53
24
|
|
|
54
25
|
## Installation
|
|
55
26
|
The recommended installation method is using [pip](http://pip-installer.org)
|
|
@@ -100,17 +71,20 @@ Using *Check that* keywords offers a large reduction in the need for variables i
|
|
|
100
71
|
|
|
101
72
|
### Time constraints
|
|
102
73
|
|
|
103
|
-
*Check that* offers support for executing checks that may take some time to complete. When using the optional `within` argument, followed by a time duration, *Check that* will apply *smart polling* to re-evaluate the expression and the keywords during the given period. Specifying the time limit is done using the standard [Robot Framework time format](https://robotframework.org/robotframework/latest/RobotFrameworkUserGuide.html#
|
|
74
|
+
*Check that* offers support for executing checks that may take some time to complete. When using the optional `within` argument, followed by a time duration, *Check that* will apply *smart polling* to re-evaluate the expression and the keywords during the given period. Specifying the time limit is done using the standard [Robot Framework time format](https://robotframework.org/robotframework/latest/RobotFrameworkUserGuide.html#time-as-time-string). It is advised to use a realistic time duration. This sets the correct expectation for the reader and helps RobotNL optimise its polling algorithm.
|
|
104
75
|
|
|
105
76
|
|**Example using time constaints**||||||
|
|
106
77
|
|---|---|---|---|---|---|
|
|
107
78
|
| Request elevator at floor | 3 |||||
|
|
108
79
|
| Check that | elevator doors are closed | within | 20 seconds ||
|
|
109
80
|
| Check that | current elevator floor | equals | 3 | within | 1 minute |
|
|
81
|
+
| Check that | elevator doors are opened | within | same timespan ||
|
|
82
|
+
|
|
83
|
+
The last line in the example uses the special argument `same timespan` to indicate that this check is linked to the same time constraint as the previous check. So, once the doors are closed, the elevator should not only reach the requested floor within 1 minute, but also the doors should be opened within that same 1-minute timespan. To use `within same timespan` you must have executed a check with a time constraint before. This is not necessarily the directly preceding line. The most recent time constraint set within scope is used as starting point. For test suites, that is the current test suite, for keywords that is the current keyword.
|
|
110
84
|
|
|
111
85
|
### Hybrid manual testing
|
|
112
86
|
|
|
113
|
-
To manually interact with your automated test run during testing or test case development,
|
|
87
|
+
To manually interact with your automated test run during testing or test case development, RobotNL offers the *Check manual* and *Check interactive* keywords. These keywords can be included at any point in the test case to suspend the test run at the current position for user input.
|
|
114
88
|
|
|
115
89
|
***Check Manual*** allows asking the tester a question. The question typically requests manual verification of an expected outcome. The answer will PASS or FAIL the test case, which is also reflected in the test report.
|
|
116
90
|
|
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
#
|
|
2
|
-
|
|
1
|
+
# RobotNL - the oneliner
|
|
2
|
+
RobotNL is a proving ground to boost Robot framework closer to Natural Language.
|
|
3
3
|
|
|
4
4
|
## Introduction
|
|
5
5
|
This project is an extension to [Robot framework](https://robotframework.org/) and although [Robot framework](https://robotframework.org/) made a very good step towards the goals of [keyword-driven testing ](https://en.wikipedia.org/wiki/Keyword-driven_testing) to make it readable for all stakeholders, there is still quite a lot of syntax involved that keeps test cases from really staying concise and to-the-point. In this project we will be introducing concepts to lift [Robot framework](https://robotframework.org/) to an even higher level.
|
|
6
6
|
|
|
7
|
-
This
|
|
7
|
+
This release introduces ``inline keywords`` and a set of ``Check that`` keywords that help to vastly reduce the amount of ``${...}`` cluttering in your test cases. Combining these concepts helps to write a cleaner [Domain Specific Language](https://en.wikipedia.org/wiki/Domain-specific_language) around your [domain vocabulary](https://en.wikipedia.org/wiki/Jargon).
|
|
8
8
|
|
|
9
9
|
## Installation
|
|
10
10
|
The recommended installation method is using [pip](http://pip-installer.org)
|
|
@@ -55,17 +55,20 @@ Using *Check that* keywords offers a large reduction in the need for variables i
|
|
|
55
55
|
|
|
56
56
|
### Time constraints
|
|
57
57
|
|
|
58
|
-
*Check that* offers support for executing checks that may take some time to complete. When using the optional `within` argument, followed by a time duration, *Check that* will apply *smart polling* to re-evaluate the expression and the keywords during the given period. Specifying the time limit is done using the standard [Robot Framework time format](https://robotframework.org/robotframework/latest/RobotFrameworkUserGuide.html#
|
|
58
|
+
*Check that* offers support for executing checks that may take some time to complete. When using the optional `within` argument, followed by a time duration, *Check that* will apply *smart polling* to re-evaluate the expression and the keywords during the given period. Specifying the time limit is done using the standard [Robot Framework time format](https://robotframework.org/robotframework/latest/RobotFrameworkUserGuide.html#time-as-time-string). It is advised to use a realistic time duration. This sets the correct expectation for the reader and helps RobotNL optimise its polling algorithm.
|
|
59
59
|
|
|
60
60
|
|**Example using time constaints**||||||
|
|
61
61
|
|---|---|---|---|---|---|
|
|
62
62
|
| Request elevator at floor | 3 |||||
|
|
63
63
|
| Check that | elevator doors are closed | within | 20 seconds ||
|
|
64
64
|
| Check that | current elevator floor | equals | 3 | within | 1 minute |
|
|
65
|
+
| Check that | elevator doors are opened | within | same timespan ||
|
|
66
|
+
|
|
67
|
+
The last line in the example uses the special argument `same timespan` to indicate that this check is linked to the same time constraint as the previous check. So, once the doors are closed, the elevator should not only reach the requested floor within 1 minute, but also the doors should be opened within that same 1-minute timespan. To use `within same timespan` you must have executed a check with a time constraint before. This is not necessarily the directly preceding line. The most recent time constraint set within scope is used as starting point. For test suites, that is the current test suite, for keywords that is the current keyword.
|
|
65
68
|
|
|
66
69
|
### Hybrid manual testing
|
|
67
70
|
|
|
68
|
-
To manually interact with your automated test run during testing or test case development,
|
|
71
|
+
To manually interact with your automated test run during testing or test case development, RobotNL offers the *Check manual* and *Check interactive* keywords. These keywords can be included at any point in the test case to suspend the test run at the current position for user input.
|
|
69
72
|
|
|
70
73
|
***Check Manual*** allows asking the tester a question. The question typically requests manual verification of an expected outcome. The answer will PASS or FAIL the test case, which is also reflected in the test report.
|
|
71
74
|
|
|
@@ -1,19 +1,19 @@
|
|
|
1
1
|
[build-system]
|
|
2
2
|
requires = [
|
|
3
|
-
"setuptools>=
|
|
3
|
+
"setuptools>=83.0.0",
|
|
4
4
|
"wheel"
|
|
5
5
|
]
|
|
6
6
|
build-backend = "setuptools.build_meta"
|
|
7
7
|
|
|
8
8
|
[project]
|
|
9
9
|
name = "robotframework-nl"
|
|
10
|
-
version = "
|
|
11
|
-
description = "
|
|
10
|
+
version = "4.0.0"
|
|
11
|
+
description = "RobotNL is a proving ground to boost Robot Framework closer to Natural Language."
|
|
12
12
|
readme = "README.md"
|
|
13
13
|
authors = [{ name = "Johan Foederer", email = "github@famfoe.nl" }]
|
|
14
|
-
license =
|
|
14
|
+
license = "BSD-3-Clause"
|
|
15
|
+
license-files = ["LICENSE"]
|
|
15
16
|
classifiers = [
|
|
16
|
-
"License :: OSI Approved :: BSD License",
|
|
17
17
|
"Programming Language :: Python :: 3",
|
|
18
18
|
"Operating System :: OS Independent",
|
|
19
19
|
]
|
|
@@ -21,7 +21,7 @@ keywords = ["robotframework", "robot", "testing", "dsl"]
|
|
|
21
21
|
dependencies = [
|
|
22
22
|
"robotframework >= 7.0",
|
|
23
23
|
]
|
|
24
|
-
requires-python = ">=3.
|
|
24
|
+
requires-python = ">=3.14"
|
|
25
25
|
|
|
26
26
|
[tool.setuptools]
|
|
27
27
|
packages = ["robotnl"]
|
|
@@ -1,55 +1,26 @@
|
|
|
1
|
-
Metadata-Version: 2.
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
2
|
Name: robotframework-nl
|
|
3
|
-
Version:
|
|
4
|
-
Summary:
|
|
3
|
+
Version: 4.0.0
|
|
4
|
+
Summary: RobotNL is a proving ground to boost Robot Framework closer to Natural Language.
|
|
5
5
|
Author-email: Johan Foederer <github@famfoe.nl>
|
|
6
|
-
License: BSD
|
|
7
|
-
|
|
8
|
-
Copyright (c) 2021, J. Foederer
|
|
9
|
-
All rights reserved.
|
|
10
|
-
|
|
11
|
-
Redistribution and use in source and binary forms, with or without
|
|
12
|
-
modification, are permitted provided that the following conditions are met:
|
|
13
|
-
|
|
14
|
-
1. Redistributions of source code must retain the above copyright notice, this
|
|
15
|
-
list of conditions and the following disclaimer.
|
|
16
|
-
|
|
17
|
-
2. Redistributions in binary form must reproduce the above copyright notice,
|
|
18
|
-
this list of conditions and the following disclaimer in the documentation
|
|
19
|
-
and/or other materials provided with the distribution.
|
|
20
|
-
|
|
21
|
-
3. Neither the name of the copyright holder nor the names of its
|
|
22
|
-
contributors may be used to endorse or promote products derived from
|
|
23
|
-
this software without specific prior written permission.
|
|
24
|
-
|
|
25
|
-
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
|
26
|
-
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
27
|
-
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
|
28
|
-
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
|
29
|
-
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
30
|
-
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
|
31
|
-
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
|
32
|
-
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
|
33
|
-
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
34
|
-
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
35
|
-
|
|
6
|
+
License-Expression: BSD-3-Clause
|
|
36
7
|
Project-URL: Homepage, https://github.com/JFoederer/robotframeworkNL
|
|
37
8
|
Keywords: robotframework,robot,testing,dsl
|
|
38
|
-
Classifier: License :: OSI Approved :: BSD License
|
|
39
9
|
Classifier: Programming Language :: Python :: 3
|
|
40
10
|
Classifier: Operating System :: OS Independent
|
|
41
|
-
Requires-Python: >=3.
|
|
11
|
+
Requires-Python: >=3.14
|
|
42
12
|
Description-Content-Type: text/markdown
|
|
43
13
|
License-File: LICENSE
|
|
44
14
|
Requires-Dist: robotframework>=7.0
|
|
15
|
+
Dynamic: license-file
|
|
45
16
|
|
|
46
|
-
#
|
|
47
|
-
|
|
17
|
+
# RobotNL - the oneliner
|
|
18
|
+
RobotNL is a proving ground to boost Robot framework closer to Natural Language.
|
|
48
19
|
|
|
49
20
|
## Introduction
|
|
50
21
|
This project is an extension to [Robot framework](https://robotframework.org/) and although [Robot framework](https://robotframework.org/) made a very good step towards the goals of [keyword-driven testing ](https://en.wikipedia.org/wiki/Keyword-driven_testing) to make it readable for all stakeholders, there is still quite a lot of syntax involved that keeps test cases from really staying concise and to-the-point. In this project we will be introducing concepts to lift [Robot framework](https://robotframework.org/) to an even higher level.
|
|
51
22
|
|
|
52
|
-
This
|
|
23
|
+
This release introduces ``inline keywords`` and a set of ``Check that`` keywords that help to vastly reduce the amount of ``${...}`` cluttering in your test cases. Combining these concepts helps to write a cleaner [Domain Specific Language](https://en.wikipedia.org/wiki/Domain-specific_language) around your [domain vocabulary](https://en.wikipedia.org/wiki/Jargon).
|
|
53
24
|
|
|
54
25
|
## Installation
|
|
55
26
|
The recommended installation method is using [pip](http://pip-installer.org)
|
|
@@ -100,17 +71,20 @@ Using *Check that* keywords offers a large reduction in the need for variables i
|
|
|
100
71
|
|
|
101
72
|
### Time constraints
|
|
102
73
|
|
|
103
|
-
*Check that* offers support for executing checks that may take some time to complete. When using the optional `within` argument, followed by a time duration, *Check that* will apply *smart polling* to re-evaluate the expression and the keywords during the given period. Specifying the time limit is done using the standard [Robot Framework time format](https://robotframework.org/robotframework/latest/RobotFrameworkUserGuide.html#
|
|
74
|
+
*Check that* offers support for executing checks that may take some time to complete. When using the optional `within` argument, followed by a time duration, *Check that* will apply *smart polling* to re-evaluate the expression and the keywords during the given period. Specifying the time limit is done using the standard [Robot Framework time format](https://robotframework.org/robotframework/latest/RobotFrameworkUserGuide.html#time-as-time-string). It is advised to use a realistic time duration. This sets the correct expectation for the reader and helps RobotNL optimise its polling algorithm.
|
|
104
75
|
|
|
105
76
|
|**Example using time constaints**||||||
|
|
106
77
|
|---|---|---|---|---|---|
|
|
107
78
|
| Request elevator at floor | 3 |||||
|
|
108
79
|
| Check that | elevator doors are closed | within | 20 seconds ||
|
|
109
80
|
| Check that | current elevator floor | equals | 3 | within | 1 minute |
|
|
81
|
+
| Check that | elevator doors are opened | within | same timespan ||
|
|
82
|
+
|
|
83
|
+
The last line in the example uses the special argument `same timespan` to indicate that this check is linked to the same time constraint as the previous check. So, once the doors are closed, the elevator should not only reach the requested floor within 1 minute, but also the doors should be opened within that same 1-minute timespan. To use `within same timespan` you must have executed a check with a time constraint before. This is not necessarily the directly preceding line. The most recent time constraint set within scope is used as starting point. For test suites, that is the current test suite, for keywords that is the current keyword.
|
|
110
84
|
|
|
111
85
|
### Hybrid manual testing
|
|
112
86
|
|
|
113
|
-
To manually interact with your automated test run during testing or test case development,
|
|
87
|
+
To manually interact with your automated test run during testing or test case development, RobotNL offers the *Check manual* and *Check interactive* keywords. These keywords can be included at any point in the test case to suspend the test run at the current position for user input.
|
|
114
88
|
|
|
115
89
|
***Check Manual*** allows asking the tester a question. The question typically requests manual verification of an expected outcome. The answer will PASS or FAIL the test case, which is also reflected in the test report.
|
|
116
90
|
|
|
@@ -48,7 +48,25 @@ class CheckFailed(RuntimeError):
|
|
|
48
48
|
class RobotChecks:
|
|
49
49
|
ROBOT_LIBRARY_SCOPE = "GLOBAL"
|
|
50
50
|
def __init__(self):
|
|
51
|
+
self.ROBOT_LIBRARY_LISTENER = self
|
|
51
52
|
self.__gui = None
|
|
53
|
+
self.scope_depth = 0
|
|
54
|
+
self.nested_timespans = {}
|
|
55
|
+
|
|
56
|
+
def _start_suite(self, data, result):
|
|
57
|
+
self.scope_depth = 0
|
|
58
|
+
self.nested_timespans = {}
|
|
59
|
+
_end_suite = _start_suite
|
|
60
|
+
|
|
61
|
+
def _start_keyword(self, data, result):
|
|
62
|
+
self.scope_depth += 1
|
|
63
|
+
|
|
64
|
+
def _end_keyword(self, data, result):
|
|
65
|
+
if self.scope_depth + 1 in self.nested_timespans:
|
|
66
|
+
# use depth+1 because 'check that' itself is also a keyword. The +1
|
|
67
|
+
# keeps all check thats on the same level grouped.
|
|
68
|
+
self.nested_timespans.pop(self.scope_depth + 1)
|
|
69
|
+
self.scope_depth -= 1
|
|
52
70
|
|
|
53
71
|
@property
|
|
54
72
|
def _gui(self):
|
|
@@ -74,7 +92,7 @@ class RobotChecks:
|
|
|
74
92
|
point where it was able to check the requirement it was testing for.
|
|
75
93
|
"""
|
|
76
94
|
try:
|
|
77
|
-
return
|
|
95
|
+
return self.__execute_check("Precondition", *args)
|
|
78
96
|
except CheckFailed as failure:
|
|
79
97
|
failure.ROBOT_CONTINUE_ON_FAILURE = False
|
|
80
98
|
raise failure
|
|
@@ -91,7 +109,7 @@ class RobotChecks:
|
|
|
91
109
|
the cause of failure.
|
|
92
110
|
"""
|
|
93
111
|
try:
|
|
94
|
-
return
|
|
112
|
+
return self.__execute_check("Postcondition", *args)
|
|
95
113
|
except CheckFailed as failure:
|
|
96
114
|
failure.ROBOT_CONTINUE_ON_FAILURE = False
|
|
97
115
|
raise failure
|
|
@@ -108,16 +126,19 @@ class RobotChecks:
|
|
|
108
126
|
Check that has two basic forms.
|
|
109
127
|
- A single keyword (with its arguments) can be evaluated to a truth value
|
|
110
128
|
- Two values or keywords (with their arguments) can be evaluated using an operator. It will
|
|
111
|
-
then have the form Check that ``<keyword or value>`` ``<operator>`` ``<keyword or value>``.
|
|
129
|
+
then have the form: Check that ``<keyword or value>`` ``<operator>`` ``<keyword or value>``.
|
|
112
130
|
|
|
113
|
-
Operator can be any Robot keyword taking
|
|
114
|
-
|
|
115
|
-
|
|
131
|
+
Operator can be any Robot keyword taking at least one argument as input. The first argument is
|
|
132
|
+
placed on the left side of the operator, the left operand. Any following arguments are placed
|
|
133
|
+
to the right of the operator and form the right operands. A keyword with its argument values is
|
|
134
|
+
treated as a single operand. A number of predefined operators on numeric, string and list types
|
|
135
|
+
are included in this library.
|
|
116
136
|
|
|
117
137
|
Examples:
|
|
118
138
|
| `Check that` | 3 | `=` | 3 |
|
|
119
139
|
| `Check that` | _Two times_ | 6 | `equals` | 12 |
|
|
120
140
|
| `Check that` | _Two times_ | 5 | `≠` | _Two times_ | 7 |
|
|
141
|
+
| `Check that` | _the shoe box_ | _contains 2 items_ |
|
|
121
142
|
| `Check that` | _Earth exists_ |
|
|
122
143
|
|
|
123
144
|
'Two times' in these examples is assumed to be defined as a Robot keyword that takes one
|
|
@@ -129,16 +150,26 @@ class RobotChecks:
|
|
|
129
150
|
This will cause the condition to be reevaluated until it becomes true, or until
|
|
130
151
|
the specified time has passed. In the latter case the test case will fail.
|
|
131
152
|
|
|
153
|
+
Multiple checks can be linked to the same time constraint by using ``same timespan``
|
|
154
|
+
as the time constraint value. Suppose the previous time constraint was 5 seconds
|
|
155
|
+
and that check took 2 seconds to complete. If the next check uses
|
|
156
|
+
``within same timespan``, then this check has the remaining 3 seconds to
|
|
157
|
+
complete.
|
|
158
|
+
|
|
132
159
|
Example with time constraint:
|
|
133
160
|
| `Check that` | _condition is true_ | within | 1 minute 30 seconds |
|
|
134
161
|
|
|
135
162
|
Elevator example:
|
|
136
|
-
| `Check that` | _elevator doors are closed_ |
|
|
137
163
|
| _Request elevator at floor_ | 3 |
|
|
138
|
-
| `Check that` | _elevator
|
|
139
|
-
| `Check that` |
|
|
164
|
+
| `Check that` | _elevator doors are closed_ | within | 20 seconds |
|
|
165
|
+
| `Check that` | _elevator floor_ | `equals` | 3 | within | 1 minute |
|
|
166
|
+
| `Check that` | _elevator doors are opened_ | within | same timespan |
|
|
167
|
+
|
|
168
|
+
In the elevator example, the doors should be closed within 20 seconds after requesting a
|
|
169
|
+
floor. Then the elevator can take a maximum of 1 minute to reach the floor and open its
|
|
170
|
+
doors. `Check that` will continue as soon as the condition is detected.
|
|
140
171
|
"""
|
|
141
|
-
return
|
|
172
|
+
return self.__execute_check("Requirement", *args)
|
|
142
173
|
RUN_KW_REGISTER.register_run_keyword('robotnl', check_that.__name__, args_to_process=0, deprecation_warning=False)
|
|
143
174
|
|
|
144
175
|
def check_manual(self, checkRequestText=""):
|
|
@@ -210,8 +241,7 @@ class RobotChecks:
|
|
|
210
241
|
except Exception as e:
|
|
211
242
|
BuiltIn().log_to_console("Error in interactive keyword '%s'\n\n%s" % (newInput, e))
|
|
212
243
|
|
|
213
|
-
|
|
214
|
-
def __execute_check(checkType, *args):
|
|
244
|
+
def __execute_check(self, checkType, *args):
|
|
215
245
|
"""
|
|
216
246
|
Parse arguments for check keyword to determine its operands, evaluate them and execute the
|
|
217
247
|
check.
|
|
@@ -223,14 +253,35 @@ class RobotChecks:
|
|
|
223
253
|
TimeOutInSeconds = 0
|
|
224
254
|
TimeRemaining = True
|
|
225
255
|
s_TimeConstraint = ""
|
|
256
|
+
StartTime = time.perf_counter()
|
|
226
257
|
if len(Arguments) >= 2 and str(Arguments[-2]).lower() == 'within':
|
|
227
|
-
|
|
228
|
-
TimeOutInSeconds = timestr_to_secs(EvaluatedTimeArg)
|
|
229
|
-
s_TimeConstraint = Arguments[-1]
|
|
258
|
+
timearg = Arguments[-1]
|
|
230
259
|
Arguments = Arguments[:-2]
|
|
260
|
+
running_timespan_start, running_timespan, s_TimeConstraint =self.nested_timespans.get(
|
|
261
|
+
self.scope_depth, (None, None, ''))
|
|
262
|
+
if str(timearg).lower() == 'same timespan':
|
|
263
|
+
if running_timespan is None:
|
|
264
|
+
BuiltIn().fail("Joint timespan expected, but was not set before this check.")
|
|
265
|
+
TimeOutInSeconds = round(running_timespan_start + running_timespan - StartTime, ndigits=3)
|
|
266
|
+
|
|
267
|
+
remaining = self._human_time(0 if TimeOutInSeconds < 0 else TimeOutInSeconds)
|
|
268
|
+
BuiltIn().log(f"Reusing joint timespan: {s_TimeConstraint}\n"
|
|
269
|
+
f"Must complete within the remaining {remaining}")
|
|
270
|
+
else:
|
|
271
|
+
try:
|
|
272
|
+
EvaluatedTimeArg, s_TimeConstraint = RobotChecks.__evaluateOperand([timearg])
|
|
273
|
+
TimeOutInSeconds = timestr_to_secs(EvaluatedTimeArg)
|
|
274
|
+
except:
|
|
275
|
+
# End any running timespan on error
|
|
276
|
+
if self.scope_depth in self.nested_timespans:
|
|
277
|
+
self.nested_timespans.pop(self.scope_depth)
|
|
278
|
+
raise
|
|
279
|
+
if is_keyword(timearg):
|
|
280
|
+
s_TimeConstraint = f"{timearg} [{secs_to_timestr(TimeOutInSeconds)}]"
|
|
281
|
+
self.nested_timespans[self.scope_depth] = (StartTime, TimeOutInSeconds, s_TimeConstraint)
|
|
231
282
|
|
|
232
283
|
if not len(Arguments):
|
|
233
|
-
BuiltIn().fail("
|
|
284
|
+
BuiltIn().fail(f"{checkType} check failed. There was nothing to check.")
|
|
234
285
|
|
|
235
286
|
############################################################################################
|
|
236
287
|
# Build expression
|
|
@@ -263,8 +314,6 @@ class RobotChecks:
|
|
|
263
314
|
# Evaluate expression
|
|
264
315
|
EvaluatedResult = None
|
|
265
316
|
|
|
266
|
-
StartTime = time.perf_counter()
|
|
267
|
-
TimeLeft = TimeOutInSeconds
|
|
268
317
|
PollMax = 20 # After 20s people start wondering: "Is it still going?" Time for an update.
|
|
269
318
|
PollMin = min(PollMax/8, TimeOutInSeconds*3/100) # Shortest delay is 3% of the target time.
|
|
270
319
|
PollDelay = PollMin # Initial poll delay will be 2x PollMin
|
|
@@ -312,8 +361,14 @@ class RobotChecks:
|
|
|
312
361
|
ReportString = f"{checkType} check on '{s_LeftOperand} {OperatorKeyword} {s_RightOperand}'"
|
|
313
362
|
|
|
314
363
|
if s_TimeConstraint:
|
|
315
|
-
|
|
364
|
+
running_start, timespan, timestr = self.nested_timespans.get(self.scope_depth, (None, None, ''))
|
|
365
|
+
if TimeRemaining and running_start != StartTime:
|
|
366
|
+
elapsed = time.perf_counter() - running_start
|
|
367
|
+
BuiltIn().log(f"Check completed {self._human_time(elapsed)} into the alotted timespan ({timestr})")
|
|
368
|
+
ReportString += f" within {timestr}"
|
|
316
369
|
if not TimeRemaining and EvaluatedResult == "passed":
|
|
370
|
+
overshoot = time.perf_counter() - (running_start + timespan)
|
|
371
|
+
BuiltIn().log(f"Check completed {self._human_time(overshoot)} too late")
|
|
317
372
|
ReportString += " (too late)"
|
|
318
373
|
raise CheckFailed(ReportString)
|
|
319
374
|
|
|
@@ -356,3 +411,10 @@ class RobotChecks:
|
|
|
356
411
|
s_Operand += f" [{s_Value}]"
|
|
357
412
|
|
|
358
413
|
return Value, s_Operand
|
|
414
|
+
|
|
415
|
+
@staticmethod
|
|
416
|
+
def _human_time(time_in_seconds: float):
|
|
417
|
+
"""return a human readable string for a time in seconds"""
|
|
418
|
+
SKIP_MILLI = 10 # Do not report milliseconds for timespans above SKIP_MILLI seconds
|
|
419
|
+
rounded_time = int(time_in_seconds) if time_in_seconds > SKIP_MILLI else round(time_in_seconds, ndigits=3)
|
|
420
|
+
return secs_to_timestr(rounded_time)
|
|
@@ -35,6 +35,7 @@ from robot.api.deco import keyword as robot_keyword
|
|
|
35
35
|
from robot.utils import type_name
|
|
36
36
|
from robot.running.arguments import TypeConverter
|
|
37
37
|
|
|
38
|
+
from annotationlib import get_annotations, Format
|
|
38
39
|
from functools import wraps
|
|
39
40
|
from typing import TypeVar, Generic, Union
|
|
40
41
|
|
|
@@ -102,7 +103,7 @@ class InlineKeywordConverter(TypeConverter):
|
|
|
102
103
|
|
|
103
104
|
def _convert(self, value):
|
|
104
105
|
if not is_keyword(value):
|
|
105
|
-
raise ValueError
|
|
106
|
+
raise ValueError("Not a keyword")
|
|
106
107
|
BuiltIn().log(f"Evaluating argument as keyword [{value}]")
|
|
107
108
|
result = BuiltIn().run_keyword(value)
|
|
108
109
|
BuiltIn().log(f"{value} → {result}")
|
|
@@ -116,11 +117,16 @@ class InlineKeywordConverter(TypeConverter):
|
|
|
116
117
|
|
|
117
118
|
return result
|
|
118
119
|
|
|
119
|
-
|
|
120
120
|
def keyword(name=None, tags=(), types=()):
|
|
121
121
|
def decorator(func):
|
|
122
|
-
|
|
123
|
-
|
|
122
|
+
annotations = get_annotations(func, format=Format.VALUE)
|
|
123
|
+
for var, type_ in annotations.items():
|
|
124
|
+
annotations[var] = Union[type_, InlineKeyword[type_]]
|
|
125
|
+
|
|
126
|
+
def new_annotate(self, format=Format.VALUE):
|
|
127
|
+
return annotations
|
|
128
|
+
func.__annotate__ = new_annotate
|
|
129
|
+
|
|
124
130
|
@robot_keyword(name, tags, types)
|
|
125
131
|
@wraps(func)
|
|
126
132
|
def wrapped(*args, **kwargs):
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
VERSION = '4.0.0'
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
VERSION = '3.1.0'
|
|
File without changes
|
|
File without changes
|
{robotframework_nl-3.1.0 → robotframework_nl-4.0.0}/robotframework_nl.egg-info/dependency_links.txt
RENAMED
|
File without changes
|
|
File without changes
|
{robotframework_nl-3.1.0 → robotframework_nl-4.0.0}/robotframework_nl.egg-info/top_level.txt
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|