-
Notifications
You must be signed in to change notification settings - Fork 2.4k
Refactor execution and result side model objects #3749
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Comments
These changes affect also pre-run modifier examples in the User Guide: Related to those examples, we need an easy way to disable setup/teardown. |
Important things to decide:
|
Relevant to your refactor: I'm trying to measure and log the execution time of tests with Setup and Teardown subtracted. I'm having a tough time using the current Listener V3 Results object to do so. Given this test:
And this code:
I get:
So the result model thinks I have 0 keywords and the running model thinks I have 3. But the running model has no start-time or end-time. So I have not figured out how to get a hold of the elapsed time for the Setup and Teardown in the end_test listener hook. |
That problem is due to keyword results being only written to output.xml and not stored in memory during execution. That's not really related to this issue, but we need to do something to that if/when we add |
Thank you. I've switched to an XML post-process system. |
- Separate For and If base classes in robot.model. - For and If not anymore based on Keyword. - They have common BodyItem base class instead. - Running side For and If use right runners automatically. - Replace Body.create with Body.create_(keyword|for|if). This is part of model refactoring (#3749).
- Test/keyword setup/teardown were not visited. - Visiting FOR/IF was totally broken. Both problems due to the ongoing model refactoring (#3749).
This issue has turned out to be bigger than originally anticipated. Everything discussed in the original description is now done, but these enhancements have uncovered other highly related problems in the model that also need to be changed. I'll update the description to list these other changes as well. Had we seen how big change this is, we might have postponed it to future releases. Because we've already done so much, and because changes are really good, I strongly believe we should finish this still before RF 4.0. |
This makes For/If being independent classes instead of extending Keyword less backwards incompatible. Related to #3749.
The main remaining task is adding
|
A decision was made today to add separate |
After all these changes this issue is about to be ready and ought to be in good enough shape for the long overdue beta 2.It's likely some tuning is still done after the beta. |
Things to be still consider include:
|
I'm started to think about representing IF/ELSE in the model and in output.xml. We currently do it so that the model has a root Another approach would be storing IF/ELSE structures so that we have a root model with
This approach might feel more natural than the current approach with
Although this could still be changed, it certainly won't be changed before RF 4.0 beta 2. |
Having an |
A problem with a generic element like |
Some more work to be done still:
|
Earlier IF/ELSE structures were represented so that `If` objects represented IF branches and they has `orelse` attribute containing next ELSE IF or ELSE branch. ELSE (IF) branches were also represented by `If` objects which, again, had `orelse`. Due to this nested structure branches needed to have both the normal `status` attribute (tells the overall status, including `orelse` status) and a separate `branch_status` attribute (tells the status of this particular branch). The nested structure was also used in output.xml: <if type='if' condition='$x > 0'> <if type='else'> <kw .../> <status status='PASS'/> </if> <status status='PASS' branchstatus='NOT RUN'/> </if> After this commit IF/ELSE structures are represented so that there's a root `If` object which has `body` containing actual IF/ELSE branches. This removes the need for `orelse` and `branch_status`, but requires adding a new model object representing the root. The old `If` class was renamed to `IfBranch` that now represent a single branch. Same structure used also in output.xml: <if> <branc type='if' condition='$x > 0'> <status status='NOT RUN'/> </branch> <branch type='else'> <kw .../> <status status='PASS'/> </if> <status status='PASS'/> </if> There are pros and cons with both ways to represent IF/ELSE structures, but overall the new approach feels more straightforward and is probably easier to understand and use for others. Notice that the parsing model still uses the `orelse` approach. There it works well and I don't think changing it would be worth the effort.
IF/ELSE model model and type constants were enhanced by the comments linked above. Class, method and attribute names were enhanced in 00c282f |
1. Internally store iteration variables in an OrderedDict instead as single string. 2. In output.xml store each variable name and value separately to be able to reconstruct variables. Part of model refactoring (#3749). Hopefully the final part.
Everything listed above now done. Closing this again. |
As #3868 demonstrates, external tools using if hasattr(tc, 'body'): # RF >= 4.0
create_keyword = tc.body.create_keyword
else: # RF < 4.0
create_keyword = tc.keywords.create
create_keyword(name=kwname, args=args) |
The
TestSuite
structures we use on the execution and result sides (robot.running.model
androbot.result.model
, respectively, with a common base classes inrobot.model
) have certain things that need to be changed:Remove
keywords
andmessages
from execution sideKeyword
objects. These keywords never actually have child keywords or messages, they just represent the keyword call with the keyword name and arguments. Basically this means moving the related code from the common base class to the result side model objects.TestSuite
objects should not havekeywords
attribute but instead should havesetup
andteardown
directly. Suites having keywords is odd in general and being able to use e.g.suite.setup
instead ofsuite.keywords.setup
is convenient.keywords
attribute used byTestCase
,For
,If
(new in RF 4.0) andUserKeyword
objects should be renamed tobody
. The body can contain FOR loops and soon also IF/ELSE in addition to keywords sobody
is a much better name thankeywords
and that's also the term parsing side model uses. The forthcomingIfElse
objects should naturally havebody
, notkeywords
, as well.Add
setup
andteadown
directly toTestCase
andUserKeyword
objects. Accessingtest.setup
is more convenient than the currenttest.keywords.setup
andtest.body.setup
would be just wrong.Make
setup
andteardown
objects, notNone
, also when they are not defined. This makes it easier for external code like pre-run modifiers to modify them. Their initial truth value should be false to make it possible to use code likeif test.setup:
.This kind of changes are naturally backwards incompatible but in my opinion better model is worth that. We should, however, preserve
keywords
as a deprecated read-only property that is generated based onbody
andsetup/teardown
when accessed.[Update on 2021-01-18] Everything discussed above has now been done, but doing these changes has uncovered other highly related problems in the model that also need to be changed:
On the execution side make
For
andIf
independent classes instead of extendingKeyword
. They don't need keyword related attributes likename
orargs
, but instead they should have context specific attributes likeFor.flavor
andIf.condition
. Earlier those context specific attributes were implemented as properties but they should be normal attributes. Old keyword specific attributes should probably be preserved as deprecated properties for backwards compatibility.Add separate
visit/start/end_for
andvisit/start/end_if
methods to the visitor interface. EarlierFor
andIf
were visited usingvisit/start/end_keyword
but that doesn't work anymore when they don't extendKeyword
.Add separate
For
andIf
classes on result side. Currently FOR and IF construct are reported as keywords withtype
set accordingly. This makes inspecting FOR/IF hard because their context specific information is not directly available and need to be parsed from keyword attributes. For example, all FOR information is in keyword name in format like${x} IN [ a | b | c ]
. This change requires some changes to output.xml as well and I added a separate comment about that.On the result side move keywords' messages to
body
to preserve their relative order with keywords and FOR/IF constructs. This makes it easier to preserve their order also in log (Relative order of messages and keywords is not preserved in log #2086). The oldmessages
attribute should be preserved as a property to make accessing only messages easy.The text was updated successfully, but these errors were encountered: