Skip to content

Commit 338af33

Browse files
committed
Enhance lineno and source with listener v2.
1. Cleanup and finalize adding `source` and `lineno` to `start/end_keyword`: - Pass both data and result objects to listener code using `ModelCombiner`. This makes `lineno` and `source` easily accessible. - Remove `lineno` and `source` from result side model objects that don't get them anyway when using Rebot. - Add tests. This includes FOR/IF and resource files. - Update User Guide. - Fixes robotframework#3538. 2. Add `source` to `start/end_test` methods: - `source` was readily available to be passed to listeners. - Add/fix tests and update User Guide. - Fixes robotframework#3856.
1 parent 9fa0954 commit 338af33

23 files changed

Lines changed: 434 additions & 135 deletions
Lines changed: 174 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,174 @@
1+
*** Settings ***
2+
Suite Setup Run Tests --listener ${LISTENER DIR}/LinenoAndSource.py ${TEST CASE FILE}
3+
Test Template Expect
4+
Test Teardown Validate keywords
5+
Resource listener_resource.robot
6+
7+
*** Variables ***
8+
${TEST CASE FILE} ${LISTENER DIR}/lineno_and_source.robot
9+
${RESOURCE FILE} ${LISTENER DIR}/lineno_and_source.resource
10+
@{EXPECTED}
11+
12+
*** Test Cases ***
13+
Keyword
14+
START No Operation 7
15+
END No Operation 7
16+
17+
User keyword
18+
START User Keyword 10
19+
START No Operation 66
20+
END No Operation 66
21+
END User Keyword 10
22+
23+
User keyword in resource
24+
START User Keyword In Resource 13
25+
START No Operation 3 source=${RESOURCE FILE}
26+
END No Operation 3 source=${RESOURCE FILE}
27+
END User Keyword In Resource 13
28+
29+
Not run keyword
30+
START Fail 17
31+
END Fail 17
32+
START Fail 18
33+
END Fail 18 run=False
34+
START Non-existing 19
35+
END Non-existing 19 run=False
36+
37+
FOR
38+
START \${x} IN [ first | second ] 22 type=FOR
39+
START \${x} = first 22 type=FOR ITERATION
40+
START No Operation 23
41+
END No Operation 23
42+
END \${x} = first 22 type=FOR ITERATION
43+
START \${x} = second 22 type=FOR ITERATION
44+
START No Operation 23
45+
END No Operation 23
46+
END \${x} = second 22 type=FOR ITERATION
47+
END \${x} IN [ first | second ] 22 type=FOR
48+
49+
FOR in keyword
50+
START FOR In Keyword 27
51+
START \${x} IN [ once ] 69 type=FOR
52+
START \${x} = once 69 type=FOR ITERATION
53+
START No Operation 70
54+
END No Operation 70
55+
END \${x} = once 69 type=FOR ITERATION
56+
END \${x} IN [ once ] 69 type=FOR
57+
END FOR In Keyword 27
58+
59+
FOR in IF
60+
START True 30 type=IF
61+
START \${x} | \${y} IN [ x | y ] 31 type=FOR
62+
START \${x} = x, \${y} = y 31 type=FOR ITERATION
63+
START No Operation 32
64+
END No Operation 32
65+
END \${x} = x, \${y} = y 31 type=FOR ITERATION
66+
END \${x} | \${y} IN [ x | y ] 31 type=FOR
67+
END True 30 type=IF
68+
69+
FOR in resource
70+
START FOR In Resource 37
71+
START \${x} IN [ once ] 6 source=${RESOURCE FILE} type=FOR
72+
START \${x} = once 6 source=${RESOURCE FILE} type=FOR ITERATION
73+
START Log 7 source=${RESOURCE FILE}
74+
END Log 7 source=${RESOURCE FILE}
75+
END \${x} = once 6 source=${RESOURCE FILE} type=FOR ITERATION
76+
END \${x} IN [ once ] 6 source=${RESOURCE FILE} type=FOR
77+
END FOR In Resource 37
78+
79+
IF
80+
START 1 > 2 40 type=IF
81+
START Fail 41
82+
END Fail 41 run=False
83+
END 1 > 2 40 run=False type=IF
84+
START 1 < 2 42 type=ELSE IF
85+
START No Operation 43
86+
END No Operation 43
87+
END 1 < 2 42 type=ELSE IF
88+
START ${EMPTY} 44 type=ELSE
89+
START Fail 45
90+
END Fail 45 run=False
91+
END ${EMPTY} 44 type=ELSE run=False
92+
93+
IF in keyword
94+
START IF In Keyword 49
95+
START True 74 type=IF
96+
START No Operation 75
97+
END No Operation 75
98+
END True 74 type=IF
99+
END IF In Keyword 49
100+
101+
IF in FOR
102+
START \${x} IN [ 1 | 2 ] 53 type=FOR
103+
START \${x} = 1 53 type=FOR ITERATION
104+
START \${x} == 1 54 type=IF
105+
START Log 55
106+
END Log 55
107+
END \${x} == 1 54 type=IF
108+
START ${EMPTY} 56 type=ELSE
109+
START Fail 57
110+
END Fail 57 run=False
111+
END ${EMPTY} 56 type=ELSE run=False
112+
END \${x} = 1 53 type=FOR ITERATION
113+
START \${x} = 2 53 type=FOR ITERATION
114+
START \${x} == 1 54 type=IF
115+
START Log 55
116+
END Log 55 run=False
117+
END \${x} == 1 54 type=IF run=False
118+
START ${EMPTY} 56 type=ELSE
119+
START Fail 57
120+
END Fail 57
121+
END ${EMPTY} 56 type=ELSE
122+
END \${x} = 2 53 type=FOR ITERATION
123+
END \${x} IN [ 1 | 2 ] 53 type=FOR
124+
125+
IF in resource
126+
START IF In Resource 62
127+
START True 11 source=${RESOURCE FILE} type=IF
128+
START No Operation 12 source=${RESOURCE FILE}
129+
END No Operation 12 source=${RESOURCE FILE}
130+
END True 11 source=${RESOURCE FILE} type=IF
131+
END IF In Resource 62
132+
133+
Test
134+
[Template] Expect test
135+
Keyword 6
136+
User keyword 9
137+
User keyword in resource 12
138+
Not run keyword 15
139+
\FOR 21
140+
FOR in keyword 26
141+
FOR in IF 29
142+
FOR in resource 36
143+
\IF 39
144+
IF in keyword 48
145+
IF in FOR 51
146+
IF in resource 61
147+
[Teardown] Validate tests
148+
149+
Suite
150+
START Lineno And Source type=SUITE
151+
END Lineno And Source type=SUITE
152+
[Teardown] Validate suite
153+
154+
*** Keywords ***
155+
Expect
156+
[Arguments] ${event} ${name} ${lineno}=-1 ${source}=${TEST CASE FILE} ${type}=KEYWORD ${run}=True
157+
${source} = Normalize Path ${source}
158+
${status} = Set Variable IF ${run} ${EMPTY} \tNOT RUN
159+
Set test variable @EXPECTED @{EXPECTED} ${event}\t${type}\t${name}\t${lineno}\t${source}${status}
160+
161+
Validate keywords
162+
Check Test Case ${TESTNAME}
163+
Check Listener File ${TEST NAME}.txt @{EXPECTED}
164+
165+
Expect test
166+
[Arguments] ${name} ${lineno}
167+
Expect START ${name} ${lineno} type=TEST
168+
Expect END ${name} ${lineno} type=TEST
169+
170+
Validate tests
171+
Check Listener File LinenoAndSourceTests.txt @{EXPECTED}
172+
173+
Validate suite
174+
Check Listener File LinenoAndSourceSuite.txt @{EXPECTED}

‎atest/robot/output/listener_interface/listener_methods.robot‎

Lines changed: 0 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -67,26 +67,6 @@ Keyword Tags
6767
${status} = Log File %{TEMPDIR}/${ATTR_TYPE_FILE}
6868
Should Contain X Times ${status} PASSED | tags: [force, keyword, tags] 6
6969

70-
FOR and IF line numbers
71-
Run Tests --listener ListenAll misc/for_loops.robot misc/if_else.robot
72-
Stderr Should Be Empty
73-
${output} = Get Listener File ${ALL FILE}
74-
FOR ${expected} IN
75-
... FOR START: \${pet} IN [ cat | dog | horse ] (line 3)
76-
... FOR ITERATION START: \${pet} = cat (line 3)
77-
... KEYWORD START: BuiltIn.Log ['\${pet}'] (line 4)
78-
... FOR ITERATION START: \${pet} = dog (line 3)
79-
... KEYWORD START: BuiltIn.Log ['\${pet}'] (line 4)
80-
... IF START: 'IF' == 'WRONG' (line 3)
81-
... IF END: NOT RUN
82-
... ELSE IF START: 'ELSE IF' == 'ELSE IF' (line 5)
83-
... KEYWORD START: BuiltIn.Log ['else if branch'] (line 6)
84-
... ELSE IF END: PASS
85-
... ELSE START: (line 7)
86-
... ELSE END: NOT RUN
87-
Should Contain ${output} ${expected}
88-
END
89-
9070
Suite And Test Counts
9171
Run Tests --listener listeners.SuiteAndTestCounts misc/suites/subsuites misc/suites/subsuites2
9272
Stderr Should Be Empty
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
import os
2+
import tempfile
3+
4+
5+
TEMPDIR = os.getenv('TEMPDIR', tempfile.gettempdir())
6+
7+
8+
class LinenoAndSource(object):
9+
ROBOT_LISTENER_API_VERSION = 2
10+
11+
def __init__(self):
12+
self.suite_output = open(os.path.join(TEMPDIR, 'LinenoAndSourceSuite.txt'), 'w')
13+
self.test_output = open(os.path.join(TEMPDIR, 'LinenoAndSourceTests.txt'), 'w')
14+
self.output = None
15+
16+
def start_suite(self, name, attrs):
17+
self.output = self.suite_output
18+
self.report('START', type='SUITE', name=name, **attrs)
19+
20+
def end_suite(self, name, attrs):
21+
self.output = self.suite_output
22+
self.report('END', type='SUITE', name=name, **attrs)
23+
24+
def start_test(self, name, attrs):
25+
self.output = self.test_output
26+
self.report('START', type='TEST', name=name, **attrs)
27+
self.output = open(os.path.join(TEMPDIR, name + '.txt'), 'w')
28+
29+
def end_test(self, name, attrs):
30+
self.output.close()
31+
self.output = self.test_output
32+
self.report('END', type='TEST', name=name, **attrs)
33+
34+
def start_keyword(self, name, attrs):
35+
self.report('START', **attrs)
36+
37+
def end_keyword(self, name, attrs):
38+
self.report('END', **attrs)
39+
40+
def close(self):
41+
self.suite_output.close()
42+
self.test_output.close()
43+
44+
def report(self, event, type, source, lineno=-1, name=None, kwname=None,
45+
status=None, **ignore):
46+
info = [event, type, name or kwname, lineno, source]
47+
if status == 'NOT RUN':
48+
info.append(status)
49+
self.output.write('\t'.join(str(i) for i in info) + '\n')
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
*** Keywords ***
2+
User Keyword In Resource
3+
No operation
4+
5+
FOR In Resource
6+
FOR ${x} IN once
7+
Log ${x}
8+
END
9+
10+
IF In Resource
11+
IF True
12+
No Operation
13+
END
Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
*** Settings ***
2+
Resource lineno_and_source.resource
3+
4+
5+
*** Test Cases ***
6+
Keyword
7+
No Operation
8+
9+
User keyword
10+
User Keyword
11+
12+
User keyword in resource
13+
User Keyword In Resource
14+
15+
Not run keyword
16+
[Documentation] FAIL This fails
17+
Fail This fails
18+
Fail Not run
19+
Non-existing
20+
21+
FOR
22+
FOR ${x} IN first second
23+
No Operation
24+
END
25+
26+
FOR in keyword
27+
FOR In keyword
28+
29+
FOR in IF
30+
IF True
31+
FOR ${x} ${y} IN x y
32+
No Operation
33+
END
34+
END
35+
36+
FOR in resource
37+
FOR In resource
38+
39+
IF
40+
IF 1 > 2
41+
Fail Should not be executed
42+
ELSE IF 1 < 2
43+
No Operation
44+
ELSE
45+
Fail Should not be executed
46+
END
47+
48+
IF in keyword
49+
IF In keyword
50+
51+
IF in FOR
52+
[Documentation] FAIL 2
53+
FOR ${x} IN 1 2
54+
IF ${x} == 1
55+
Log ${x}
56+
ELSE
57+
Fail ${x}
58+
END
59+
END
60+
61+
IF in resource
62+
IF In resource
63+
64+
*** Keywords ***
65+
User Keyword
66+
No Operation
67+
68+
FOR In Keyword
69+
FOR ${x} IN once
70+
No Operation
71+
END
72+
73+
IF In Keyword
74+
IF True
75+
No Operation
76+
END
12 Bytes
Binary file not shown.

‎atest/testresources/listeners/JavaAttributeVerifyingListener.java‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -46,12 +46,12 @@ public void endSuite(String name, Map attrs) {
4646

4747
public void startTest(String name, Map attrs) {
4848
verifyAttributes("START TEST", attrs,
49-
new String[] {"id", "doc", "starttime", "longname", "origname", "tags", "template", "lineno"});
49+
new String[] {"id", "doc", "starttime", "longname", "origname", "tags", "template", "source", "lineno"});
5050
}
5151

5252
public void endTest(String name, Map attrs) {
5353
verifyAttributes("END TEST", attrs,
54-
new String[] {"id", "doc", "starttime", "longname", "origname", "tags", "template", "lineno", "endtime", "elapsedtime", "status", "message"});
54+
new String[] {"id", "doc", "starttime", "longname", "origname", "tags", "template", "source", "lineno", "endtime", "elapsedtime", "status", "message"});
5555
}
5656

5757
public void startKeyword(String name, Map attrs) {

‎atest/testresources/listeners/attributeverifyinglistener.py‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,8 @@
1414
START = 'doc starttime '
1515
END = START + 'endtime elapsedtime status '
1616
SUITE = 'id longname metadata source tests suites totaltests '
17-
TEST = 'id longname tags template originalname lineno '
18-
KW = ' kwname libname args assign tags type lineno source'
17+
TEST = 'id longname tags template originalname source lineno '
18+
KW = 'kwname libname args assign tags type lineno source '
1919
EXPECTED_TYPES = {'tags': [basestring], 'args': [basestring],
2020
'assign': [basestring], 'metadata': {basestring: basestring},
2121
'tests': [basestring], 'suites': [basestring],

0 commit comments

Comments
 (0)