def test_TemplateArguments(self): # Test # [Template] Templated Keyword # ${arg1} 2 tokens = [ Token(Token.SEPARATOR, ' '), Token(Token.ARGUMENT, '${arg1}'), Token(Token.SEPARATOR, ' '), Token(Token.ARGUMENT, '2'), Token(Token.EOL, '\n') ] assert_created_statement(tokens, TemplateArguments, args=['${arg1}', '2'])
def test_set_errors_explicitly(self): error = Error([]) error.errors = ('explicitly set', 'errors') assert_equal(error.errors, ('explicitly set', 'errors')) error.tokens = [ Token('ERROR', error='normal error'), Token('FATAL ERROR', error='fatal error') ] assert_equal( error.errors, ('normal error', 'fatal error', 'explicitly set', 'errors')) error.errors = ['errors', 'as', 'list'] assert_equal(error.errors, ('normal error', 'fatal error', 'errors', 'as', 'list'))
def test_if(self): model = get_model('''\ *** Test Cases *** Example IF True Keyword ''', data_only=True) node = model.sections[0].body[0].body[0] expected = If( header=InlineIfHeader([Token(Token.INLINE_IF, 'IF', 3, 4), Token(Token.ARGUMENT, 'True', 3, 10)]), body=[KeywordCall([Token(Token.KEYWORD, 'Keyword', 3, 18)])], end=End([Token(Token.END, '', 3, 25)]) ) assert_model(node, expected)
def test_if(self): data = ''' *** Test Cases *** Example IF True Keyword ''' expected = If( header=InlineIfHeader([ Token(Token.INLINE_IF, 'IF', 3, 4), Token(Token.ARGUMENT, 'True', 3, 10) ]), body=[KeywordCall([Token(Token.KEYWORD, 'Keyword', 3, 18)])], end=End([Token(Token.END, '', 3, 25)])) get_and_assert_model(data, expected)
def test_break(self): model = get_model('''\ *** Keywords *** Name WHILE True Break BREAK BREAK END ''', data_only=True) expected = KeywordSection( header=SectionHeader( tokens=[Token(Token.KEYWORD_HEADER, '*** Keywords ***', 1, 0) ]), body=[ Keyword( header=KeywordName( tokens=[Token(Token.KEYWORD_NAME, 'Name', 2, 0)]), body=[ While(header=WhileHeader([ Token(Token.WHILE, 'WHILE', 3, 4), Token(Token.ARGUMENT, 'True', 3, 13) ]), body=[ KeywordCall([ Token(Token.KEYWORD, 'Break', 4, 8), Token(Token.ARGUMENT, 'BREAK', 4, 17) ]), Break([Token(Token.BREAK, 'BREAK', 5, 8)]) ], end=End([Token(Token.END, 'END', 6, 4)])) ], ) ]) assert_model(model.sections[0], expected)
def test_valid(self): model = get_model('''\ *** Variables *** ${x} value @{y}= two values &{z} = one=item ''', data_only=True) expected = VariableSection(header=SectionHeader( tokens=[Token(Token.VARIABLE_HEADER, '*** Variables ***', 1, 0)]), body=[ Variable([ Token(Token.VARIABLE, '${x}', 2, 0), Token(Token.ARGUMENT, 'value', 2, 10) ]), Variable([ Token(Token.VARIABLE, '@{y}=', 3, 0), Token(Token.ARGUMENT, 'two', 3, 10), Token(Token.ARGUMENT, 'values', 3, 17) ]), Variable([ Token(Token.VARIABLE, '&{z} =', 4, 0), Token(Token.ARGUMENT, 'one=item', 4, 10) ]), ]) assert_model(model.sections[0], expected)
def test_assign_only_inside(self): data = ''' *** Test Cases *** Example IF ${cond} ${assign} ''' expected = If( header=InlineIfHeader([ Token(Token.INLINE_IF, 'IF', 3, 4), Token(Token.ARGUMENT, '${cond}', 3, 10) ]), body=[KeywordCall([Token(Token.ASSIGN, '${assign}', 3, 21)])], end=End([Token(Token.END, '', 3, 30)]), errors=('Inline IF branches cannot contain assignments.', )) get_and_assert_model(data, expected)
def test_Template(self): # Test # [Template] Keyword Name tokens = [ Token(Token.SEPARATOR, ' '), Token(Token.TEMPLATE, '[Template]'), Token(Token.SEPARATOR, ' '), Token(Token.NAME, 'Keyword Name'), Token(Token.EOL, '\n') ] assert_created_statement( tokens, Template, value='Keyword Name' )
def test_Timeout(self): # Test # [Timeout] 1 min tokens = [ Token(Token.SEPARATOR, ' '), Token(Token.TIMEOUT, '[Timeout]'), Token(Token.SEPARATOR, ' '), Token(Token.ARGUMENT, '1 min'), Token(Token.EOL, '\n') ] assert_created_statement( tokens, Timeout, value='1 min' )
def test_ElseIfHeader(self): # Test/Keyword # ELSE IF ${var} not in [@{list}] tokens = [ Token(Token.SEPARATOR, ' '), Token(Token.ELSE_IF), Token(Token.SEPARATOR, ' '), Token(Token.ARGUMENT, '${var} not in [@{list}]'), Token(Token.EOL, '\n') ] assert_created_statement( tokens, ElseIfHeader, condition='${var} not in [@{list}]' )
def test_invalid(self): data = ''' *** Test Cases *** Example TRY invalid ELSE invalid FINALLY invalid # EXCEPT AS invalid ''' expected = Try( header=TryHeader( tokens=[ Token(Token.TRY, 'TRY', 3, 4), Token(Token.ARGUMENT, 'invalid', 3, 20) ], errors=("TRY does not accept arguments, got 'invalid'.", )), next=Try( header=ElseHeader( tokens=[ Token(Token.ELSE, 'ELSE', 4, 4), Token(Token.ARGUMENT, 'invalid', 4, 20) ], errors=( "ELSE does not accept arguments, got 'invalid'.", )), errors=('ELSE branch cannot be empty.', ), next=Try(header=FinallyHeader( tokens=[ Token(Token.FINALLY, 'FINALLY', 6, 4), Token(Token.ARGUMENT, 'invalid', 6, 20) ], errors=( "FINALLY does not accept arguments, got 'invalid'.", )), errors=('FINALLY branch cannot be empty.', ), next=Try(header=ExceptHeader( tokens=[ Token(Token.EXCEPT, 'EXCEPT', 8, 4), Token(Token.AS, 'AS', 8, 14), Token(Token.VARIABLE, 'invalid', 8, 20) ], errors=( "EXCEPT's AS variable 'invalid' is invalid.", )), errors=( 'EXCEPT branch cannot be empty.', ))), ), errors=('TRY branch cannot be empty.', 'EXCEPT not allowed after ELSE.', 'EXCEPT not allowed after FINALLY.', 'TRY must have closing END.')) get_and_assert_model(data, expected)
def test_in_test_case_body_inside_try_except(self): for data_only in [True, False]: with self.subTest(data_only=data_only): model = get_model('''\ *** Test Cases *** Example TRY RETURN EXCEPT RETURN ELSE RETURN FINALLY RETURN END ''', data_only=data_only) tryroot = model.sections[0].body[0].body[0] node = tryroot.body[0] expected = ReturnStatement( [Token(Token.RETURN_STATEMENT, 'RETURN', 4, 8)], errors=('RETURN can only be used inside a user keyword.',) ) remove_non_data_nodes_and_assert(node, expected, data_only) expected.tokens[0].lineno = 6 remove_non_data_nodes_and_assert(tryroot.next.body[0], expected, data_only) expected.tokens[0].lineno = 8 remove_non_data_nodes_and_assert(tryroot.next.next.body[0], expected, data_only) expected.tokens[0].lineno = 10 remove_non_data_nodes_and_assert(tryroot.next.next.next.body[0], expected, data_only)
def test_in_test_case_body_inside_if_else(self): for data_only in [True, False]: with self.subTest(data_only=data_only): model = get_model('''\ *** Test Cases *** Example IF True RETURN ELSE IF False RETURN ELSE RETURN END ''', data_only=data_only) ifroot = model.sections[0].body[0].body[0] node = ifroot.body[0] expected = ReturnStatement( [Token(Token.RETURN_STATEMENT, 'RETURN', 4, 8)], errors=('RETURN can only be used inside a user keyword.',) ) remove_non_data_nodes_and_assert(node, expected, data_only) expected.tokens[0].lineno = 6 remove_non_data_nodes_and_assert(ifroot.orelse.body[0], expected, data_only) expected.tokens[0].lineno = 8 remove_non_data_nodes_and_assert(ifroot.orelse.orelse.body[0], expected, data_only)
def test_invalid(self): model = get_model('''\ *** Test Cases *** Example IF too many ELSE ooops ELSE IF END ooops IF ''', data_only=True) if1, if2 = model.sections[0].body[0].body expected1 = If( header=IfHeader( tokens=[Token(Token.IF, 'IF', 3, 4), Token(Token.ARGUMENT, 'too', 3, 10), Token(Token.ARGUMENT, 'many', 3, 17)], errors=('IF has more than one condition.',) ), orelse=If( header=ElseHeader( tokens=[Token(Token.ELSE, 'ELSE', 4, 4), Token(Token.ARGUMENT, 'ooops', 4, 12)], errors=('ELSE has condition.',) ), orelse=If( header=ElseIfHeader( tokens=[Token(Token.ELSE_IF, 'ELSE IF', 5, 4)], errors=('ELSE IF has no condition.',) ), errors=('ELSE IF has empty body.',) ), errors=('ELSE has empty body.',) ), end=End( tokens=[Token(Token.END, 'END', 6, 4), Token(Token.ARGUMENT, 'ooops', 6, 11)], errors=('END does not accept arguments.',) ), errors=('IF has empty body.', 'ELSE IF after ELSE.') ) expected2 = If( header=IfHeader( tokens=[Token(Token.IF, 'IF', 8, 4)], errors=('IF has no condition.',) ), errors=('IF has empty body.', 'IF has no closing END.') ) assert_model(if1, expected1) assert_model(if2, expected2)
def visit_Statement(self, statement): if statement[-1].type != Token.EOL: if not self._should_write_content_after_name(statement): statement.tokens.append(Token(Token.EOL, self._newline)) for line in statement.lines: if line[-1].type == Token.EOL: line[-1].value = self._newline return statement
def assert_tokens(tokens, expected): assert_equal(len(tokens), len(expected)) for act, exp in zip(tokens, expected): exp = Token(*exp) assert_equal(act.type, exp.type) assert_equal(act.value, exp.value) assert_equal(act.lineno, exp.lineno) assert_equal(act.columnno, exp.columnno)
def assert_tokens(source, expected, get_tokens=get_tokens, data_only=False): tokens = list(get_tokens(source, data_only)) assert_equal(len(tokens), len(expected), 'Expected %d tokens:\n%s\n\nGot %d tokens:\n%s' % (len(expected), expected, len(tokens), tokens), values=False) for act, exp in zip(tokens, expected): assert_equal(act, Token(*exp), formatter=repr)
def test_EmptyLine(self): tokens = [ Token(Token.EOL, '\n') ] assert_created_statement( tokens, EmptyLine, eol='\n' )
def _insert_leading_and_trailing_separators(self, line): """Add missing separators to the beginning and the end of the line. When converting from spaces to pipes, a seprator token is needed in the beginning of the line, for each indent level and in the end of the line. """ separators_needed = 1 if self.indent > 1: # TXT format has 1 separator token regardless of the indent level. # With pipes, we need to add one separator for each indent level # beyond 1 separators_needed += self.indent - 1 for _ in range(separators_needed): line = [Token(Token.SEPARATOR, '')] + line if len(line) > 1: if line[-2].type != Token.SEPARATOR: line = line[:-1] + [Token(Token.SEPARATOR, ''), line[-1]] return line
def test_invalid(self): data = ''' *** Test Cases *** Example WHILE too many values # Empty body END ''' expected = While(header=WhileHeader( tokens=[ Token(Token.WHILE, 'WHILE', 3, 4), Token(Token.ARGUMENT, 'too', 3, 13), Token(Token.ARGUMENT, 'many', 3, 20), Token(Token.ARGUMENT, 'values', 3, 28) ], errors=('WHILE cannot have more than one condition.', )), end=End([Token(Token.END, 'END', 5, 4)]), errors=('WHILE loop cannot be empty.', )) get_and_assert_model(data, expected)
def test_nested(self): model = get_model('''\ *** Test Cases *** Example IF ${x} IF ${y} K1 ELSE IF ${z} K2 ''', data_only=True) node = model.sections[0].body[0].body[0] expected = If( header=InlineIfHeader([ Token(Token.INLINE_IF, 'IF', 3, 4), Token(Token.ARGUMENT, '${x}', 3, 10) ]), body=[ If( header=InlineIfHeader([ Token(Token.INLINE_IF, 'IF', 3, 18), Token(Token.ARGUMENT, '${y}', 3, 24) ]), body=[KeywordCall([Token(Token.KEYWORD, 'K1', 3, 32)])], orelse=If( header=ElseHeader([Token(Token.ELSE, 'ELSE', 3, 38)]), body=[ If( header=InlineIfHeader([ Token(Token.INLINE_IF, 'IF', 3, 46), Token(Token.ARGUMENT, '${z}', 3, 52) ]), body=[ KeywordCall( [Token(Token.KEYWORD, 'K2', 3, 60)]) ], end=End([Token(Token.END, '', 3, 62)]), ) ], ), errors=('Inline IF cannot be nested.', ), ) ], errors=('Inline IF cannot be nested.', ), ) assert_model(node, expected)
def test_ModelTransformer(self): class Transformer(ModelTransformer): def visit_SectionHeader(self, node): return node def visit_TestCaseName(self, node): return node def visit_Statement(self, node): return None def visit_Block(self, node): self.generic_visit(node) if hasattr(node, 'header'): for token in node.header.data_tokens: token.value = token.value.upper() return node model = get_model('''\ *** Test Cases *** Example [Tags] to be removed To be removed ''') Transformer().visit(model) expected = File(sections=[ TestCaseSection( header=SectionHeader([ Token('TESTCASE HEADER', '*** TEST CASES ***', 1, 0), Token('EOL', '\n', 1, 18) ]), body=[ TestCase(TestCaseName([ Token('TESTCASE NAME', 'EXAMPLE', 2, 0), Token('EOL', '\n', 2, 7) ])), ] ) ]) assert_model(model, expected)
def test_valid(self): data = ''' *** Test Cases *** Example WHILE True Log ${x} END ''' expected = While(header=WhileHeader([ Token(Token.WHILE, 'WHILE', 3, 4), Token(Token.ARGUMENT, 'True', 3, 13), ]), body=[ KeywordCall([ Token(Token.KEYWORD, 'Log', 4, 8), Token(Token.ARGUMENT, '${x}', 4, 15) ]) ], end=End([Token(Token.END, 'END', 5, 4)])) get_and_assert_model(data, expected)
def test_invalid(self): model = get_model('''\ *** Test Cases *** Example IF too many ELSE ooops ELSE IF ''', data_only=True) node = model.sections[0].body[0].body[0] expected = If( header=IfHeader([ Token(Token.IF, 'IF', 3, 4), Token(Token.ARGUMENT, 'too', 3, 10), Token(Token.ARGUMENT, 'many', 3, 17), ]), orelse=If(header=ElseHeader([ Token(Token.ELSE, 'ELSE', 4, 4), Token(Token.ARGUMENT, 'ooops', 4, 12) ]), orelse=If(header=ElseIfHeader( [Token(Token.ELSE_IF, 'ELSE IF', 5, 4)]), errors=[ 'ELSE IF has no condition.', 'ELSE IF has empty body.' ]), errors=['ELSE has condition.', 'ELSE has empty body.']), errors=[ 'IF has more than one condition.', 'IF has empty body.', 'ELSE IF after ELSE.', 'IF has no closing END.' ]) assert_model(node, expected)
def test_return(self): model = get_model('''\ *** Keywords *** Name Return RETURN RETURN RETURN ''', data_only=True) expected = KeywordSection( header=SectionHeader( tokens=[Token(Token.KEYWORD_HEADER, '*** Keywords ***', 1, 0) ]), body=[ Keyword( header=KeywordName( tokens=[Token(Token.KEYWORD_NAME, 'Name', 2, 0)]), body=[ KeywordCall([ Token(Token.KEYWORD, 'Return', 3, 4), Token(Token.ARGUMENT, 'RETURN', 3, 14) ]), ReturnStatement([ Token(Token.RETURN_STATEMENT, 'RETURN', 4, 4), Token(Token.ARGUMENT, 'RETURN', 4, 14) ]) ], ) ]) assert_model(model.sections[0], expected)
def test_invalid(self): model = get_model('''\ *** Test Cases *** Example FOR END ooops FOR wrong IN ''', data_only=True) loop1, loop2 = model.sections[0].body[0].body expected1 = For(header=ForHeader( tokens=[Token(Token.FOR, 'FOR', 3, 4)], errors=('FOR loop has no loop variables.', "FOR loop has no 'IN' or other valid separator."), ), end=End(tokens=[ Token(Token.END, 'END', 4, 4), Token(Token.ARGUMENT, 'ooops', 4, 11) ], errors=('END does not accept arguments.', )), errors=('FOR loop has empty body.', )) expected2 = For(header=ForHeader( tokens=[ Token(Token.FOR, 'FOR', 6, 4), Token(Token.VARIABLE, 'wrong', 6, 11), Token(Token.FOR_SEPARATOR, 'IN', 6, 20) ], errors=("FOR loop has invalid loop variable 'wrong'.", "FOR loop has no loop values."), ), errors=('FOR loop has empty body.', 'FOR loop has no closing END.')) assert_model(loop1, expected1) assert_model(loop2, expected2)
def test_nested(self): data = ''' *** Test Cases *** Example IF ${x} IF ${y} K1 ELSE IF ${z} K2 ''' expected = If( header=InlineIfHeader([ Token(Token.INLINE_IF, 'IF', 3, 4), Token(Token.ARGUMENT, '${x}', 3, 10) ]), body=[ If( header=InlineIfHeader([ Token(Token.INLINE_IF, 'IF', 3, 18), Token(Token.ARGUMENT, '${y}', 3, 24) ]), body=[KeywordCall([Token(Token.KEYWORD, 'K1', 3, 32)])], orelse=If( header=ElseHeader([Token(Token.ELSE, 'ELSE', 3, 38)]), body=[ If( header=InlineIfHeader([ Token(Token.INLINE_IF, 'IF', 3, 46), Token(Token.ARGUMENT, '${z}', 3, 52) ]), body=[ KeywordCall( [Token(Token.KEYWORD, 'K2', 3, 60)]) ], end=End([Token(Token.END, '', 3, 62)]), ) ], ), errors=('Inline IF cannot be nested.', ), ) ], errors=('Inline IF cannot be nested.', ), ) get_and_assert_model(data, expected)
def test_in_test_case_body(self): for data_only in [True, False]: with self.subTest(data_only=data_only): model = get_model('''\ *** Test Cases *** Example RETURN''', data_only=data_only) node = model.sections[0].body[0].body[0] expected = ReturnStatement( [Token(Token.RETURN_STATEMENT, 'RETURN', 3, 4)], errors=('RETURN can only be used inside a user keyword.',) ) remove_non_data_nodes_and_assert(node, expected, data_only)
def test_in_uk_body(self): for data_only in [True, False]: with self.subTest(data_only=data_only): model = get_model('''\ *** Keywords *** Example CONTINUE''', data_only=data_only) node = model.sections[0].body[0].body[0] expected = Continue( [Token(Token.CONTINUE, 'CONTINUE', 3, 4)], errors=('CONTINUE can only be used inside a loop.',) ) remove_non_data_nodes_and_assert(node, expected, data_only)
def test_in_test_case_body(self): for data_only in [True, False]: with self.subTest(data_only=data_only): model = get_model('''\ *** Test Cases *** Example BREAK''', data_only=data_only) node = model.sections[0].body[0].body[0] expected = Break( [Token(Token.BREAK, 'BREAK', 3, 4)], errors=('BREAK can only be used inside a loop.',) ) remove_non_data_nodes_and_assert(node, expected, data_only)