def test_if_else_if_else(self): model = get_model('''\ *** Test Cases *** Example IF True K1 ELSE IF False K2 ELSE K3 ''', 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, 'K1', 3, 18)])], orelse=If( header=ElseIfHeader([ Token(Token.ELSE_IF, 'ELSE IF', 3, 24), Token(Token.ARGUMENT, 'False', 3, 35) ]), body=[KeywordCall([Token(Token.KEYWORD, 'K2', 3, 44)])], orelse=If( header=ElseHeader([Token(Token.ELSE, 'ELSE', 3, 50)]), body=[KeywordCall([Token(Token.KEYWORD, 'K3', 3, 58)])], )), end=End([Token(Token.END, '', 3, 60)])) assert_model(node, expected)
def test_valid(self): model = get_model('''\ *** Test Cases *** Example FOR ${x} IN a b c Log ${x} END ''', data_only=True) loop = model.sections[0].body[0].body[0] expected = For(header=ForHeader([ Token(Token.FOR, 'FOR', 3, 4), Token(Token.VARIABLE, '${x}', 3, 11), Token(Token.FOR_SEPARATOR, 'IN', 3, 19), Token(Token.ARGUMENT, 'a', 3, 25), Token(Token.ARGUMENT, 'b', 3, 30), Token(Token.ARGUMENT, 'c', 3, 35), ]), body=[ KeywordCall([ Token(Token.KEYWORD, 'Log', 4, 8), Token(Token.ARGUMENT, '${x}', 4, 15) ]) ], end=End([Token(Token.END, 'END', 5, 4)])) assert_model(loop, 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_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_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_model_error_with_error_and_fatal_error(self): model = get_resource_model('''\ *** Invalid *** *** Settings *** Invalid Documentation *** Test Cases *** ''', data_only=True) inv_header = ( "Unrecognized section header '*** Invalid ***'. Valid sections: " "'Settings', 'Variables', 'Keywords' and 'Comments'.") inv_setting = "Non-existing setting 'Invalid'." inv_testcases = "Resource file with 'Test Cases' section is invalid." expected = File([ CommentSection(body=[ Error([Token('ERROR', '*** Invalid ***', 1, 0, inv_header)]) ]), SettingSection( header=SectionHeader( [Token('SETTING HEADER', '*** Settings ***', 2, 0)]), body=[ Error([Token('ERROR', 'Invalid', 3, 0, inv_setting)]), Documentation( [Token('DOCUMENTATION', 'Documentation', 4, 0)]), Error([ Token('FATAL ERROR', '*** Test Cases ***', 5, 0, inv_testcases) ]) ]) ]) assert_model(model, expected)
def test_ast_NodeTransformer(self): class Transformer(ast.NodeTransformer): def visit_Tags(self, node): return None def visit_TestCaseSection(self, node): self.generic_visit(node) node.body.append( TestCase( TestCaseName([ Token('TESTCASE NAME', 'Added'), Token('EOL', '\n') ]))) return node def visit_TestCase(self, node): self.generic_visit(node) return node if node.name != 'REMOVE' else None def visit_TestCaseName(self, node): name_token = node.get_token(Token.TESTCASE_NAME) name_token.value = name_token.value.upper() return node def visit_Block(self, node): raise RuntimeError('Should not be executed.') def visit_Statement(self, node): raise RuntimeError('Should not be executed.') model = get_model('''\ *** Test Cases *** Example [Tags] to be removed Remove ''') 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) ])), TestCase( TestCaseName([ Token('TESTCASE NAME', 'Added'), Token('EOL', '\n') ])) ]) ]) assert_model(model, expected)
def get_and_assert_model(data, expected, depth=2): for data_only in True, False: model = get_model(data.strip(), data_only=data_only) if not data_only: remove_non_data(model) node = model.sections[0] for _ in range(depth): node = node.body[0] assert_model(node, expected)
def test_invalid(self): model = get_model('''\ *** Variables *** Ooops I did it again ${} invalid ${x}== invalid ${not closed invalid &{dict} invalid ${invalid} ''', data_only=True) expected = VariableSection( header=SectionHeader(tokens=[ Token(Token.VARIABLE_HEADER, '*** Variables ***', 1, 0) ]), body=[ Variable(tokens=[ Token(Token.VARIABLE, 'Ooops', 2, 0), Token(Token.ARGUMENT, 'I did it again', 2, 10) ], errors=("Invalid variable name 'Ooops'.", )), Variable(tokens=[ Token(Token.VARIABLE, '${}', 3, 0), Token(Token.ARGUMENT, 'invalid', 3, 10) ], errors=("Invalid variable name '${}'.", )), Variable(tokens=[ Token(Token.VARIABLE, '${x}==', 4, 0), Token(Token.ARGUMENT, 'invalid', 4, 10) ], errors=("Invalid variable name '${x}=='.", )), Variable(tokens=[ Token(Token.VARIABLE, '${not', 5, 0), Token(Token.ARGUMENT, 'closed', 5, 10) ], errors=("Invalid variable name '${not'.", )), Variable(tokens=[ Token(Token.VARIABLE, '', 6, 0), Token(Token.ARGUMENT, 'invalid', 6, 10) ], errors=("Invalid variable name ''.", )), Variable( tokens=[ Token(Token.VARIABLE, '&{dict}', 7, 0), Token(Token.ARGUMENT, 'invalid', 7, 10), Token(Token.ARGUMENT, '${invalid}', 7, 21) ], errors= ("Invalid dictionary variable item 'invalid'. " "Items must use 'name=value' syntax or be dictionary variables themselves.", "Invalid dictionary variable item '${invalid}'. " "Items must use 'name=value' syntax or be dictionary variables themselves." )), ]) assert_model(model.sections[0], expected)
def test_model_error_with_fatal_error(self): model = get_resource_model('''\ *** Test Cases *** ''', data_only=True) inv_testcases = "Resource file with 'Test Cases' section is invalid." expected = File([ CommentSection(body=[ Error([ Token('FATAL ERROR', '*** Test Cases ***', 1, 0, inv_testcases) ]) ]) ]) assert_model(model, expected)
def test_nested(self): model = get_model('''\ *** Test Cases *** Example IF ${x} Log ${x} IF ${y} Log ${y} ELSE Log ${z} END END ''', data_only=True) node = model.sections[0].body[0].body[0] expected = If(header=IfHeader([ Token(Token.IF, 'IF', 3, 4), Token(Token.ARGUMENT, '${x}', 3, 10), ]), body=[ KeywordCall([ Token(Token.KEYWORD, 'Log', 4, 8), Token(Token.ARGUMENT, '${x}', 4, 15) ]), If(header=IfHeader([ Token(Token.IF, 'IF', 5, 8), Token(Token.ARGUMENT, '${y}', 5, 14), ]), body=[ KeywordCall([ Token(Token.KEYWORD, 'Log', 6, 12), Token(Token.ARGUMENT, '${y}', 6, 19) ]) ], orelse=If(header=ElseHeader( [Token(Token.ELSE, 'ELSE', 7, 8)]), body=[ KeywordCall([ Token(Token.KEYWORD, 'Log', 8, 12), Token(Token.ARGUMENT, '${z}', 8, 19) ]) ]), end=End([Token(Token.END, 'END', 9, 8)])) ], end=End([Token(Token.END, 'END', 10, 4)])) assert_model(node, expected)
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_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_header_parsing(self): model = get_model('''\ *** Test Cases *** Example WHILE True limit=100 Log ${x} END ''', data_only=False) header = model.sections[0].body[0].body[0].header expected = WhileHeader([ Token(Token.SEPARATOR, ' ', 3, 0), Token(Token.WHILE, 'WHILE', 3, 4), Token(Token.SEPARATOR, ' ', 3, 9), Token(Token.ARGUMENT, 'True', 3, 13), Token(Token.SEPARATOR, ' ', 3, 17), Token(Token.OPTION, 'limit=100', 3, 21), Token(Token.EOL, '\n', 3, 30), ]) assert_model(header, expected)
def test_assign(self): model = get_model('''\ *** Test Cases *** Example ${x} = IF True K1 ELSE K2 ''', data_only=True) node = model.sections[0].body[0].body[0] expected = If( header=InlineIfHeader([ Token(Token.ASSIGN, '${x} =', 3, 4), Token(Token.INLINE_IF, 'IF', 3, 14), Token(Token.ARGUMENT, 'True', 3, 20) ]), body=[KeywordCall([Token(Token.KEYWORD, 'K1', 3, 28)])], orelse=If( header=ElseHeader([Token(Token.ELSE, 'ELSE', 3, 34)]), body=[KeywordCall([Token(Token.KEYWORD, 'K2', 3, 42)])], ), end=End([Token(Token.END, '', 3, 44)])) 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_invalid(self): model = get_model('''\ *** Test Cases *** Example IF 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)], errors=('IF must have a condition.', )), orelse=If(header=ElseHeader( tokens=[ Token(Token.ELSE, 'ELSE', 4, 4), Token(Token.ARGUMENT, 'ooops', 4, 12) ], errors=("ELSE does not accept arguments, got 'ooops'.", )), orelse=If(header=ElseIfHeader( tokens=[Token(Token.ELSE_IF, 'ELSE IF', 5, 4)], errors=('ELSE IF must have a condition.', )), errors=('ELSE IF branch cannot be empty.', )), errors=('ELSE branch cannot be empty.', )), end=End(tokens=[ Token(Token.END, 'END', 6, 4), Token(Token.ARGUMENT, 'ooops', 6, 11) ], errors=("END does not accept arguments, got 'ooops'.", )), errors=('IF branch cannot be empty.', 'ELSE IF after ELSE.')) expected2 = If(header=IfHeader(tokens=[Token(Token.IF, 'IF', 8, 4)], errors=('IF must have a condition.', )), errors=('IF branch cannot be empty.', 'IF has no closing END.')) assert_model(if1, expected1) assert_model(if2, expected2)
def test_valid(self): model = get_model('''\ *** Test Cases *** Example WHILE True Log ${x} END ''', data_only=True) loop = model.sections[0].body[0].body[0] 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)])) assert_model(loop, expected)
def test_continue(self): model = get_model('''\ *** Keywords *** Name FOR ${x} IN @{stuff} Continue CONTINUE CONTINUE 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=[ For(header=ForHeader([ Token(Token.FOR, 'FOR', 3, 4), Token(Token.VARIABLE, '${x}', 3, 11), Token(Token.FOR_SEPARATOR, 'IN', 3, 19), Token(Token.ARGUMENT, '@{stuff}', 3, 25) ]), body=[ KeywordCall([ Token(Token.KEYWORD, 'Continue', 4, 8), Token(Token.ARGUMENT, 'CONTINUE', 4, 20) ]), Continue( [Token(Token.CONTINUE, 'CONTINUE', 5, 8)]) ], end=End([Token(Token.END, 'END', 6, 4)])) ], ) ]) assert_model(model.sections[0], expected)
def test_invalid_arg_spec(self): model = get_model('''\ *** Keywords *** Invalid [Arguments] ooops ${optional}=default ${required} ... @{too} @{many} &{notlast} ${x} ''', data_only=True) expected = KeywordSection( header=SectionHeader( tokens=[Token(Token.KEYWORD_HEADER, '*** Keywords ***', 1, 0) ]), body=[ Keyword( header=KeywordName( tokens=[Token(Token.KEYWORD_NAME, 'Invalid', 2, 0)]), body=[ Arguments( tokens=[ Token(Token.ARGUMENTS, '[Arguments]', 3, 4), Token(Token.ARGUMENT, 'ooops', 3, 19), Token(Token.ARGUMENT, '${optional}=default', 3, 28), Token(Token.ARGUMENT, '${required}', 3, 51), Token(Token.ARGUMENT, '@{too}', 4, 11), Token(Token.ARGUMENT, '@{many}', 4, 21), Token(Token.ARGUMENT, '&{notlast}', 4, 32), Token(Token.ARGUMENT, '${x}', 4, 46) ], errors=( "Invalid argument syntax 'ooops'.", 'Non-default argument after default arguments.', 'Cannot have multiple varargs.', 'Only last argument can be kwargs.')) ], ) ]) 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, got 'ooops'.", )), 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_if(self): model = get_model('''\ *** Test Cases *** Example IF True Keyword Another argument END ''', data_only=True) node = model.sections[0].body[0].body[0] expected = If(header=IfHeader([ Token(Token.IF, 'IF', 3, 4), Token(Token.ARGUMENT, 'True', 3, 10), ]), body=[ KeywordCall([Token(Token.KEYWORD, 'Keyword', 4, 8)]), KeywordCall([ Token(Token.KEYWORD, 'Another', 5, 8), Token(Token.ARGUMENT, 'argument', 5, 19) ]) ], end=End([Token(Token.END, 'END', 6, 4)])) assert_model(node, expected)
def test_invalid(self): model = get_model('''\ *** Test Cases *** Example ${x} = ${y} IF ELSE ooops ELSE IF ''', data_only=True) node = model.sections[0].body[0].body[0] expected = If( header=InlineIfHeader([ Token(Token.ASSIGN, '${x} =', 3, 4), Token(Token.ASSIGN, '${y}', 3, 14), Token(Token.INLINE_IF, 'IF', 3, 22), Token(Token.ARGUMENT, 'ELSE', 3, 28) ]), body=[KeywordCall([Token(Token.KEYWORD, 'ooops', 3, 36)])], orelse=If( header=ElseIfHeader( [Token(Token.ELSE_IF, 'ELSE IF', 3, 45)], errors=('ELSE IF must have a condition.', )), errors=('ELSE IF branch cannot be empty.', ), ), end=End([Token(Token.END, '', 3, 52)])) assert_model(node, expected)
def test_nested(self): model = get_model('''\ *** Test Cases *** Example FOR ${x} IN 1 2 FOR ${y} IN RANGE ${x} Log ${y} END END ''', data_only=True) loop = model.sections[0].body[0].body[0] expected = For(header=ForHeader([ Token(Token.FOR, 'FOR', 3, 4), Token(Token.VARIABLE, '${x}', 3, 11), Token(Token.FOR_SEPARATOR, 'IN', 3, 19), Token(Token.ARGUMENT, '1', 3, 25), Token(Token.ARGUMENT, '2', 3, 30), ]), body=[ For(header=ForHeader([ Token(Token.FOR, 'FOR', 4, 8), Token(Token.VARIABLE, '${y}', 4, 15), Token(Token.FOR_SEPARATOR, 'IN RANGE', 4, 23), Token(Token.ARGUMENT, '${x}', 4, 35), ]), body=[ KeywordCall([ Token(Token.KEYWORD, 'Log', 5, 12), Token(Token.ARGUMENT, '${y}', 5, 19) ]) ], end=End([Token(Token.END, 'END', 6, 8)])) ], end=End([Token(Token.END, 'END', 7, 4)])) assert_model(loop, expected)
def remove_non_data_nodes_and_assert(node, expected, data_only): if not data_only: RemoveNonDataTokensVisitor().visit(node) assert_model(node, expected)
def test_save_to_different_path_as_path(self): model = get_model(PATH) different = PATH + '.robot' model.save(Path(different)) assert_model(get_model(different), EXPECTED, source=different)
def test_save_to_original_path_as_path(self): model = get_model(Path(PATH)) os.remove(PATH) model.save() assert_model(get_model(PATH), EXPECTED, source=PATH)
def test_from_open_file(self): with open(PATH) as f: model = get_model(f) assert_model(model, EXPECTED)
def test_from_path_as_path(self): model = get_model(Path(PATH)) assert_model(model, EXPECTED, source=PATH)
def test_from_string(self): model = get_model(DATA) assert_model(model, EXPECTED)