Robot Framework
model.py
Go to the documentation of this file.
1 # Copyright 2008-2015 Nokia Networks
2 # Copyright 2016- Robot Framework Foundation
3 #
4 # Licensed under the Apache License, Version 2.0 (the "License");
5 # you may not use this file except in compliance with the License.
6 # You may obtain a copy of the License at
7 #
8 # http://www.apache.org/licenses/LICENSE-2.0
9 #
10 # Unless required by applicable law or agreed to in writing, software
11 # distributed under the License is distributed on an "AS IS" BASIS,
12 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 # See the License for the specific language governing permissions and
14 # limitations under the License.
15 
16 
34 
35 from collections import OrderedDict
36 from itertools import chain
37 import warnings
38 
39 from robot import model
40 from robot.model import BodyItem, Keywords, TotalStatisticsBuilder
41 from robot.utils import get_elapsed_time, setter
42 
43 from .configurer import SuiteConfigurer
44 from .messagefilter import MessageFilter
45 from .modeldeprecation import deprecated, DeprecatedAttributesMixin
46 from .keywordremover import KeywordRemover
47 from .suiteteardownfailed import SuiteTeardownFailed, SuiteTeardownFailureHandler
48 
49 
51  __slots__ = []
52 
53 
55  __slots__ = []
56 
57 
59  __slots__ = ['iteration_class']
60 
61  def __init__(self, iteration_class, parent=None, items=None):
62  self.iteration_classiteration_class = iteration_class
63  super().__init__(parent, items)
64 
65  def create_iteration(self, *args, **kwargs):
66  return self.appendappend(self.iteration_classiteration_class(*args, **kwargs))
67 
68 
69 @Body.register
70 @Branches.register
71 @Iterations.register
73  __slots__ = []
74 
75 
77  __slots__ = []
78  PASS = 'PASS'
79  FAIL = 'FAIL'
80  SKIP = 'SKIP'
81  NOT_RUN = 'NOT RUN'
82  NOT_SET = 'NOT SET'
83 
84  @property
85 
86  elapsedtime = property
87 
88  def elapsedtime(self):
89  return get_elapsed_time(self.starttime, self.endtime)
90 
91  @property
92 
93  passed = property
94 
95  def passed(self):
96  return self.statusstatus == self.PASSPASS
97 
98  @passed.setter
99 
100  def passed(self, passed):
101  self.statusstatus = self.PASSPASS if passed else self.FAILFAIL
102 
103  @property
104 
105  failed = property
106 
107  def failed(self):
108  return self.statusstatus == self.FAILFAIL
109 
110  @failed.setter
111 
112  def failed(self, failed):
113  self.statusstatus = self.FAILFAIL if failed else self.PASSPASS
114 
115  @property
116 
120  skipped = property
121 
122  def skipped(self):
123  return self.statusstatus == self.SKIPSKIP
124 
125  @skipped.setter
126 
127  def skipped(self, skipped):
128  if not skipped:
129  raise ValueError("`skipped` value must be truthy, got '%s'." % skipped)
130  self.statusstatus = self.SKIPSKIP
131 
132  @property
133 
137  not_run = property
138 
139  def not_run(self):
140  return self.statusstatus == self.NOT_RUNNOT_RUN
141 
142  @not_run.setter
143 
144  def not_run(self, not_run):
145  if not not_run:
146  raise ValueError("`not_run` value must be truthy, got '%s'." % not_run)
147  self.statusstatus = self.NOT_RUNNOT_RUN
148 
149 
150 
152  type = BodyItem.ITERATION
153  body_class = Body
154  repr_args = ('variables',)
155  __slots__ = ['variables', 'status', 'starttime', 'endtime', 'doc']
156 
157  def __init__(self, variables=None, status='FAIL', starttime=None, endtime=None,
158  doc='', parent=None):
159  self.variablesvariables = variables or OrderedDict()
160  self.parentparent = parent
161  self.statusstatusstatus = status
162  self.starttimestarttime = starttime
163  self.endtimeendtime = endtime
164  self.docdoc = doc
165  self.bodybodybody = None
166 
167  @setter
168  def body(self, body):
169  return self.body_classbody_class(self, body)
170 
171  def visit(self, visitor):
172  visitor.visit_for_iteration(self)
173 
174  @property
175  @deprecated
176  name = property
177 
178  def name(self):
179  return ', '.join('%s = %s' % item for item in self.variablesvariables.items())
180 
181 
182 @Body.register
184  iterations_class = Iterations
185  iteration_class = ForIteration
186  __slots__ = ['status', 'starttime', 'endtime', 'doc']
187 
188  def __init__(self, variables=(), flavor='IN', values=(), status='FAIL',
189  starttime=None, endtime=None, doc='', parent=None):
190  super().__init__(variables, flavor, values, parent)
191  self.statusstatusstatus = status
192  self.starttimestarttime = starttime
193  self.endtimeendtime = endtime
194  self.docdoc = doc
195 
196  @setter
197  def body(self, iterations):
198  return self.iterations_classiterations_class(self.iteration_classiteration_class, self, iterations)
199 
200  @property
201  @deprecated
202  name = property
203 
204  def name(self):
205  return '%s %s [ %s ]' % (' | '.join(self.variablesvariables), self.flavorflavor,
206  ' | '.join(self.valuesvalues))
207 
208 
209 
211  type = BodyItem.ITERATION
212  body_class = Body
213  __slots__ = ['status', 'starttime', 'endtime', 'doc']
214 
215  def __init__(self, status='FAIL', starttime=None, endtime=None,
216  doc='', parent=None):
217  self.parentparent = parent
218  self.statusstatusstatus = status
219  self.starttimestarttime = starttime
220  self.endtimeendtime = endtime
221  self.docdoc = doc
222  self.bodybodybody = None
223 
224  @setter
225  def body(self, body):
226  return self.body_classbody_class(self, body)
227 
228  def visit(self, visitor):
229  visitor.visit_while_iteration(self)
230 
231  @property
232  @deprecated
233  name = property
234 
235  def name(self):
236  return ''
237 
238 
239 @Body.register
241  iterations_class = Iterations
242  iteration_class = WhileIteration
243  __slots__ = ['status', 'starttime', 'endtime', 'doc']
244 
245  def __init__(self, condition=None, limit=None, parent=None, status='FAIL',
246  starttime=None, endtime=None, doc=''):
247  super().__init__(condition, limit, parent)
248  self.statusstatusstatus = status
249  self.starttimestarttime = starttime
250  self.endtimeendtime = endtime
251  self.docdoc = doc
252 
253  @setter
254  def body(self, iterations):
255  return self.iterations_classiterations_class(self.iteration_classiteration_class, self, iterations)
256 
257  @property
258  @deprecated
259  name = property
260 
261  def name(self):
262  parts = []
263  if self.conditioncondition:
264  parts.append(self.conditioncondition)
265  if self.limitlimit:
266  parts.append(f'limit={self.limit}')
267  return ' | '.join(parts)
268 
269 
271  body_class = Body
272  __slots__ = ['status', 'starttime', 'endtime', 'doc']
273 
274  def __init__(self, type=BodyItem.IF, condition=None, status='FAIL',
275  starttime=None, endtime=None, doc='', parent=None):
276  super().__init__(type, condition, parent)
277  self.statusstatusstatus = status
278  self.starttimestarttime = starttime
279  self.endtimeendtime = endtime
280  self.docdoc = doc
281 
282  @property
283  @deprecated
284  name = property
285 
286  def name(self):
287  return self.conditioncondition
288 
289 
290 @Body.register
292  branch_class = IfBranch
293  branches_class = Branches
294  __slots__ = ['status', 'starttime', 'endtime', 'doc']
295 
296  def __init__(self, status='FAIL', starttime=None, endtime=None, doc='', parent=None):
297  super().__init__(parent)
298  self.statusstatusstatus = status
299  self.starttimestarttime = starttime
300  self.endtimeendtime = endtime
301  self.docdoc = doc
302 
303 
305  body_class = Body
306  __slots__ = ['status', 'starttime', 'endtime', 'doc']
307 
308  def __init__(self, type=BodyItem.TRY, patterns=(), pattern_type=None, variable=None,
309  status='FAIL', starttime=None, endtime=None, doc='', parent=None):
310  super().__init__(type, patterns, pattern_type, variable, parent)
311  self.statusstatusstatus = status
312  self.starttimestarttime = starttime
313  self.endtimeendtime = endtime
314  self.docdoc = doc
315 
316  @property
317  @deprecated
318  name = property
319 
320  def name(self):
321  patterns = list(self.patternspatterns)
322  if self.pattern_typepattern_type:
323  patterns.append(f'type={self.pattern_type}')
324  parts = []
325  if patterns:
326  parts.append(' | '.join(patterns))
327  if self.variablevariable:
328  parts.append(f'AS {self.variable}')
329  return ' '.join(parts)
330 
331 
332 @Body.register
334  branch_class = TryBranch
335  branches_class = Branches
336  __slots__ = ['status', 'starttime', 'endtime', 'doc']
337 
338  def __init__(self, status='FAIL', starttime=None, endtime=None, doc='', parent=None):
339  super().__init__(parent)
340  self.statusstatusstatus = status
341  self.starttimestarttime = starttime
342  self.endtimeendtime = endtime
343  self.docdoc = doc
344 
345 
346 @Body.register
348  __slots__ = ['status', 'starttime', 'endtime']
349  body_class = Body
350 
351  def __init__(self, values=(), status='FAIL', starttime=None, endtime=None, parent=None):
352  super().__init__(values, parent)
353  self.statusstatusstatus = status
354  self.starttimestarttime = starttime
355  self.endtimeendtime = endtime
356  self.bodybodybody = None
357 
358  @setter
359 
365  def body(self, body):
366  return self.body_classbody_class(self, body)
367 
368  @property
369  @deprecated
370  args = property
371 
372  def args(self):
373  return self.valuesvalues
374 
375  @property
376  @deprecated
377  doc = property
378 
379  def doc(self):
380  return ''
381 
382 
383 @Body.register
385  __slots__ = ['status', 'starttime', 'endtime']
386  body_class = Body
387 
388  def __init__(self, status='FAIL', starttime=None, endtime=None, parent=None):
389  super().__init__(parent)
390  self.statusstatusstatus = status
391  self.starttimestarttime = starttime
392  self.endtimeendtime = endtime
393  self.bodybodybody = None
394 
395  @setter
396 
402  def body(self, body):
403  return self.body_classbody_class(self, body)
404 
405  @property
406  @deprecated
407  args = property
408 
409  def args(self):
410  return ()
411 
412  @property
413  @deprecated
414  doc = property
415 
416  def doc(self):
417  return ''
418 
419 
420 @Body.register
422  __slots__ = ['status', 'starttime', 'endtime']
423  body_class = Body
424 
425  def __init__(self, status='FAIL', starttime=None, endtime=None, parent=None):
426  super().__init__(parent)
427  self.statusstatusstatus = status
428  self.starttimestarttime = starttime
429  self.endtimeendtime = endtime
430  self.bodybodybody = None
431 
432  @setter
433 
439  def body(self, body):
440  return self.body_classbody_class(self, body)
441 
442  @property
443  @deprecated
444  args = property
445 
446  def args(self):
447  return ()
448 
449  @property
450  @deprecated
451  doc = property
452 
453  def doc(self):
454  return ''
455 
456 
457 @Body.register
458 @Branches.register
459 @Iterations.register
460 
465  body_class = Body
466  __slots__ = ['kwname', 'libname', 'status', 'starttime', 'endtime', 'message',
467  'sourcename']
468 
469  def __init__(self, kwname='', libname='', doc='', args=(), assign=(), tags=(),
470  timeout=None, type=BodyItem.KEYWORD, status='FAIL', starttime=None,
471  endtime=None, parent=None, sourcename=None):
472  super().__init__(None, doc, args, assign, tags, timeout, type, parent)
473  #: Name of the keyword without library or resource name.
474  self.kwnamekwname = kwname
475  #: Name of the library or resource containing this keyword.
476  self.libnamelibname = libname
477  #: Execution status as a string. ``PASS``, ``FAIL``, ``SKIP`` or ``NOT RUN``.
478  self.statusstatusstatus = status
479  #: Keyword execution start time in format ``%Y%m%d %H:%M:%S.%f``.
480  self.starttimestarttime = starttime
481  #: Keyword execution end time in format ``%Y%m%d %H:%M:%S.%f``.
482  self.endtimeendtime = endtime
483  #: Keyword status message. Used only if suite teardowns fails.
484  self.messagemessage = ''
485  #: Original name of keyword with embedded arguments.
486  self.sourcenamesourcename = sourcename
487  self.bodybodybody = None
488 
489  @setter
490 
491  def body(self, body):
492  return self.body_classbody_class(self, body)
493 
494  @property
495 
499  keywords = property
500 
501  def keywords(self):
502  keywords = self.bodybodybody.filter(messages=False)
503  if self.teardownteardownteardownteardown:
504  keywords.append(self.teardownteardownteardownteardown)
505  return Keywords(self, keywords)
506 
507  @keywords.setter
508 
509  def keywords(self, keywords):
510  Keywords.raise_deprecation_error()
511 
512  @property
513 
518  messages = property
519 
520  def messages(self):
521  return self.bodybodybody.filter(messages=True)
522 
523  @property
524 
528  children = property
529 
530  def children(self):
531  warnings.warn("'Keyword.children' is deprecated. Use 'Keyword.body' instead.")
532  return list(self.bodybodybody)
533 
534  @property
535 
544  name = property
545 
546  def name(self):
547  if not self.libnamelibname:
548  return self.kwnamekwname
549  return '%s.%s' % (self.libnamelibname, self.kwnamekwname)
550 
551  @name.setter
552 
553  def name(self, name):
554  if name is not None:
555  raise AttributeError("Cannot set 'name' attribute directly. "
556  "Set 'kwname' and 'libname' separately instead.")
557  self.kwnamekwname = None
558  self.libnamelibname = None
559 
560 
561 
566  __slots__ = ['status', 'message', 'starttime', 'endtime']
567  body_class = Body
568  fixture_class = Keyword
569 
570  def __init__(self, name='', doc='', tags=None, timeout=None, lineno=None,
571  status='FAIL', message='', starttime=None, endtime=None,
572  parent=None):
573  super().__init__(name, doc, tags, timeout, lineno, parent)
574  #: Status as a string ``PASS`` or ``FAIL``. See also :attr:`passed`.
575  self.statusstatusstatus = status
576  #: Test message. Typically a failure message but can be set also when
577  #: test passes.
578  self.messagemessage = message
579  #: Test case execution start time in format ``%Y%m%d %H:%M:%S.%f``.
580  self.starttimestarttime = starttime
581  #: Test case execution end time in format ``%Y%m%d %H:%M:%S.%f``.
582  self.endtimeendtime = endtime
583 
584  @property
585  not_run = property
586 
587  def not_run(self):
588  return False
589 
590  @property
591  critical = property
592 
593  def critical(self):
594  warnings.warn("'TestCase.critical' is deprecated and always returns 'True'.")
595  return True
596 
597 
598 
603  __slots__ = ['message', 'starttime', 'endtime']
604  test_class = TestCase
605  fixture_class = Keyword
606 
607  def __init__(self, name='', doc='', metadata=None, source=None, message='',
608  starttime=None, endtime=None, rpa=False, parent=None):
609  super().__init__(name, doc, metadata, source, rpa, parent)
610  #: Possible suite setup or teardown error message.
611  self.messagemessage = message
612  #: Suite execution start time in format ``%Y%m%d %H:%M:%S.%f``.
613  self.starttimestarttime = starttime
614  #: Suite execution end time in format ``%Y%m%d %H:%M:%S.%f``.
615  self.endtimeendtime = endtime
616 
617  @property
618 
619  passed = property
620 
621  def passed(self):
622  return self.statusstatusstatusstatus == self.PASSPASS
623 
624  @property
625 
626  failed = property
627 
628  def failed(self):
629  return self.statusstatusstatusstatus == self.FAILFAIL
630 
631  @property
632 
633  skipped = property
634 
635  def skipped(self):
636  return self.statusstatusstatusstatus == self.SKIPSKIP
637 
638  @property
639  not_run = property
640 
641  def not_run(self):
642  return False
643 
644  @property
645 
652  status = property
653 
654  def status(self):
655  stats = self.statisticsstatisticsstatistics # Local variable avoids recreating stats.
656  if stats.failed:
657  return self.FAILFAIL
658  if stats.passed:
659  return self.PASSPASS
660  return self.SKIPSKIP
661 
662  @property
663 
673  statistics = property
674 
675  def statistics(self):
676  return TotalStatisticsBuilder(self, self.rparpa).stats
677 
678  @property
679 
680  full_message = property
681 
682  def full_message(self):
683  if not self.messagemessage:
684  return self.stat_messagestat_messagestat_message
685  return '%s\n\n%s' % (self.messagemessage, self.stat_messagestat_messagestat_message)
686 
687  @property
688 
689  stat_message = property
690 
691  def stat_message(self):
692  return self.statisticsstatisticsstatistics.message
693 
694  @property
695 
696  elapsedtime = property
697 
698  def elapsedtime(self):
699  if self.starttimestarttime and self.endtimeendtime:
700  return get_elapsed_time(self.starttimestarttime, self.endtimeendtime)
701  return sum(child.elapsedtime for child in
702  chain(self.suitessuitessuites, self.teststeststests, (self.setupsetupsetupsetup, self.teardownteardownteardownteardown)))
703 
704 
712  def remove_keywords(self, how):
713  self.visitvisit(KeywordRemover(how))
714 
715 
716  def filter_messages(self, log_level='TRACE'):
717  self.visitvisit(MessageFilter(log_level))
718 
719 
736  def configure(self, **options):
737  model.TestSuite.configure(self) # Parent validates call is allowed.
738  self.visitvisit(SuiteConfigurer(**options))
739 
740 
743 
744 
745  def suite_teardown_failed(self, error):
746  self.visitvisit(SuiteTeardownFailed(error))
747 
748 
749  def suite_teardown_skipped(self, message):
750  self.visitvisit(SuiteTeardownFailed(message, skipped=True))
Base class for Body and Branches objects.
Definition: body.py:86
def append(self, item)
Definition: itemlist.py:36
def teardown(self, teardown)
Definition: keyword.py:96
teardown
Keyword teardown as a :class:Keyword object.
Definition: keyword.py:87
A list-like object representing keywords in a suite, a test or a keyword.
Definition: keyword.py:137
teardown
Suite teardown as a :class:~.model.keyword.Keyword object.
Definition: testsuite.py:156
def suites(self, suites)
Child suites as a :class:~.TestSuites object.
Definition: testsuite.py:90
def visit(self, visitor)
:mod:Visitor interface <robot.model.visitor> entry-point.
Definition: testsuite.py:288
def tests(self, tests)
Tests as a :class:~.TestCases object.
Definition: testsuite.py:95
def teardown(self, teardown)
Definition: testsuite.py:165
setup
Suite setup as a :class:~.model.keyword.Keyword object.
Definition: testsuite.py:122
def body(self, body)
Child keywords and messages as a :class:~.Body object.
Definition: model.py:439
def __init__(self, status='FAIL', starttime=None, endtime=None, parent=None)
Definition: model.py:425
def body(self, body)
Child keywords and messages as a :class:~.Body object.
Definition: model.py:402
def __init__(self, status='FAIL', starttime=None, endtime=None, parent=None)
Definition: model.py:388
Represents one FOR loop iteration.
Definition: model.py:151
def __init__(self, variables=None, status='FAIL', starttime=None, endtime=None, doc='', parent=None)
Definition: model.py:158
def body(self, body)
Definition: model.py:168
def visit(self, visitor)
Definition: model.py:171
def __init__(self, variables=(), flavor='IN', values=(), status='FAIL', starttime=None, endtime=None, doc='', parent=None)
Definition: model.py:189
def __init__(self, type=BodyItem.IF, condition=None, status='FAIL', starttime=None, endtime=None, doc='', parent=None)
Definition: model.py:275
def __init__(self, status='FAIL', starttime=None, endtime=None, doc='', parent=None)
Definition: model.py:296
def create_iteration(self, *args, **kwargs)
Definition: model.py:65
def __init__(self, iteration_class, parent=None, items=None)
Definition: model.py:61
Represents results of a single keyword.
Definition: model.py:464
def body(self, body)
Child keywords and messages as a :class:~.Body object.
Definition: model.py:491
name
Keyword name in format libname.kwname.
Definition: model.py:544
children
List of child keywords and messages in creation order.
Definition: model.py:528
messages
Keyword's messages.
Definition: model.py:518
def __init__(self, kwname='', libname='', doc='', args=(), assign=(), tags=(), timeout=None, type=BodyItem.KEYWORD, status='FAIL', starttime=None, endtime=None, parent=None, sourcename=None)
Definition: model.py:471
keywords
Deprecated since Robot Framework 4.0.
Definition: model.py:499
def __init__(self, values=(), status='FAIL', starttime=None, endtime=None, parent=None)
Definition: model.py:351
def body(self, body)
Child keywords and messages as a :class:~.Body object.
Definition: model.py:365
not_run
True when :attr:status is 'NOT RUN', False otherwise.
Definition: model.py:137
skipped
True when :attr:status is 'SKIP', False otherwise.
Definition: model.py:120
passed
True when :attr:status is 'PASS', False otherwise.
Definition: model.py:93
failed
True when :attr:status is 'FAIL', False otherwise.
Definition: model.py:105
elapsedtime
Total execution time in milliseconds.
Definition: model.py:86
Represents results of a single test case.
Definition: model.py:565
def __init__(self, name='', doc='', tags=None, timeout=None, lineno=None, status='FAIL', message='', starttime=None, endtime=None, parent=None)
Definition: model.py:572
Represents results of a single test suite.
Definition: model.py:602
def __init__(self, name='', doc='', metadata=None, source=None, message='', starttime=None, endtime=None, rpa=False, parent=None)
Definition: model.py:608
elapsedtime
Total execution time in milliseconds.
Definition: model.py:696
skipped
True if there are no passed or failed tests, False otherwise.
Definition: model.py:633
def filter_messages(self, log_level='TRACE')
Remove log messages below the specified log_level.
Definition: model.py:716
stat_message
String representation of the :attr:statistics.
Definition: model.py:689
def remove_keywords(self, how)
Remove keywords based on the given condition.
Definition: model.py:712
def suite_teardown_skipped(self, message)
Internal usage only.
Definition: model.py:749
passed
True if no test has failed but some have passed, False otherwise.
Definition: model.py:619
def handle_suite_teardown_failures(self)
Internal usage only.
Definition: model.py:741
status
'PASS', 'FAIL' or 'SKIP' depending on test statuses.
Definition: model.py:652
def configure(self, **options)
A shortcut to configure a suite using one method call.
Definition: model.py:736
def suite_teardown_failed(self, error)
Internal usage only.
Definition: model.py:745
full_message
Combination of :attr:message and :attr:stat_message.
Definition: model.py:680
statistics
Suite statistics as a :class:~robot.model.totalstatistics.TotalStatistics object.
Definition: model.py:673
failed
True if any test has failed, False otherwise.
Definition: model.py:626
def __init__(self, type=BodyItem.TRY, patterns=(), pattern_type=None, variable=None, status='FAIL', starttime=None, endtime=None, doc='', parent=None)
Definition: model.py:309
def __init__(self, status='FAIL', starttime=None, endtime=None, doc='', parent=None)
Definition: model.py:338
Represents one WHILE loop iteration.
Definition: model.py:210
def __init__(self, status='FAIL', starttime=None, endtime=None, doc='', parent=None)
Definition: model.py:216
def visit(self, visitor)
Definition: model.py:228
def __init__(self, condition=None, limit=None, parent=None, status='FAIL', starttime=None, endtime=None, doc='')
Definition: model.py:246
def get_elapsed_time(start_time, end_time)
Returns the time between given timestamps in milliseconds.
Definition: robottime.py:359