Giter VIP home page Giter VIP logo

robomachine's Introduction

RoboMachine

A test data generator for Robot Framework.

What is this tool for?

You know those ugly bugs that users report that somehow were missed by all your ATDD-, TDD- and exploratory testing? Those bugs that lurk in the corners of complexity of the system that you are building. Those bugs that will make users of your application hate you..

This tool is here to help you seek and destroy those bugs before users will find them.

It gives you the ability to generate a huge number of tests that can go through a very vast number of similar (or not so similar) test scenarios.

What is it?

If you know Regular Expressions: A regular expression is a pattern that represents all the possible strings that match that pattern. RoboMachine works in a similar way. A machine represents a set of tests in a compact way. This machine can be used to generate all (or part of) the tests that it represents.

If you know Model-Based Testing or automata theory: With RoboMachine you define an extended finite state machine (in a Robot Framework -like syntax) that represents a set of tests. RoboMachine also contains algorithms that can be used to generate real executable Robot Framework tests from a RoboMachine model.

If you know Combinatorial Testing or like data driven testing: With RoboMachine you can define sets of data and rules about that data, that can be used to generate data driven tests (and also keyword driven tests). This allows you to keep your data in compact sets and let the system generate the real test data vectors from there.

What does it look like?

Here is an example machine (using combinatorial techniques) that can generate tests for SeleniumLibrary demo.

*** Settings ***
Suite Setup     Open Browser  ${LOGIN_PAGE_URL}   googlechrome
Suite Teardown  Close Browser
Test Setup      Go to  ${LOGIN_PAGE_URL}
Library         SeleniumLibrary

*** Variables ***
${USERNAME_FIELD}  username_field
${PASSWORD_FIELD}  password_field
${LOGIN_BUTTON}    LOGIN
${VALID_USERNAME}  demo
${VALID_PASSWORD}  mode
${LOGIN_PAGE_URL}  http://localhost:7272/html/

*** Machine ***
${USERNAME}  any of  ${VALID_USERNAME}  ${VALID_PASSWORD}  invalid123  ${EMPTY}
${PASSWORD}  any of  ${VALID_PASSWORD}  ${VALID_USERNAME}  password123  ${EMPTY}

# Add an equivalence rule to reduce the number of generated tests
${USERNAME} == ${VALID_PASSWORD}  <==>  ${PASSWORD} == ${VALID_USERNAME}

Login Page
  Title Should Be  Login Page
  [Actions]
    Submit Credentials  ==>  Welcome Page  when  ${USERNAME} == ${VALID_USERNAME}  and  ${PASSWORD} == ${VALID_PASSWORD}
    Submit Credentials  ==>  Error Page    otherwise

Welcome Page
  Title Should Be  Welcome Page

Error Page
  Title Should Be  Error Page

*** Keywords ***
Submit Credentials
  Input Text      ${USERNAME_FIELD}  ${USERNAME}
  Input Password  ${PASSWORD_FIELD}  ${PASSWORD}
  Click Button    ${LOGIN_BUTTON}

Here is another example machine (using model-based testing with finite state machine):

*** Settings ***
Suite Setup     Open Browser  ${LOGIN_PAGE_URL}   googlechrome
Suite Teardown  Close Browser
Test Setup      Go to  ${LOGIN_PAGE_URL}
Library         SeleniumLibrary

*** Variables ***
${USERNAME_FIELD}  username_field
${PASSWORD_FIELD}  password_field
${LOGIN_BUTTON}    LOGIN
${VALID_USERNAME}  demo
${VALID_PASSWORD}  mode
${LOGIN_PAGE_URL}  http://localhost:7272/html/

*** Machine ***
Login Page
  Title Should Be  Login Page
  [Actions]
    Submit Valid Credentials  ==>  Welcome Page
    Submit Invalid Credentials  ==>  Error Page

Welcome Page
  Title Should Be  Welcome Page
  [Actions]
    Go to  ${LOGIN_PAGE_URL}  ==>  Login Page

Error Page
  Title Should Be  Error Page
  [Actions]
    Go to  ${LOGIN_PAGE_URL}  ==>  Login Page

*** Keywords ***
Submit Valid Credentials
  Submit Credentials  ${VALID_USERNAME}  ${VALID_PASSWORD}

Submit Invalid Credentials
  Submit Credentials  invalid_username   invalid_password

Submit Credentials
  [Arguments]     ${username}        ${password}
  Input Text      ${USERNAME_FIELD}  ${USERNAME}
  Input Password  ${PASSWORD_FIELD}  ${PASSWORD}
  Click Button    ${LOGIN_BUTTON}

NOTE! This machine can generate infinite number of test sequences thus you need to constraint the generation. For example:

robomachine --tests-max 10 --actions-max 20 --to-state 'Welcome Page' --generation-algorithm random [MACHINE_FILE_NAME]

will generate 10 random tests with at most 20 actions each and all tests ending to state 'Welcome Page'.

Installation

From Python Package Index

pip install RoboMachine

From source:

git clone git://github.com/mkorpela/RoboMachine.git
cd RoboMachine
python setup.py install

After this you should have a commandline tool called robomachine available. See robomachine --help for commandline tool usage.

Syntax

  • Only supported Robot Framework format is space separated format.
  • You should use .robomachine suffix for your Machine files.
  • You can have a Robot Framework Settings table at the beginning of the machine file.
  • You can have a Robot Framework Variables table after the optional Settings table.
  • Machine table is a must.
  • You can have a Robot Framework Keywords table after the Machine table.

Machine table syntax

Used machine variables must be introduced at the beginning of the machine table. Valid machine variable is a valid Robot Framework variable that contains only uppercase characters A-Z, numbers (not at the start) 0-9 and underscores (_). For example: ${VALID_123} is a valid machine variable.

An example of a valid machine variable definition line::

${VALID_VARIABLE_1}  any of  Value 1  Value 2  Value 3

Rules about the machine variables should be next. Rule building blocks:

  • Variable conditions:
    • ${VARIABLE} == value
    • ${VARIABLE} != value
    • ${VARIABLE} < value
    • ${VARIABLE} <= value
    • ${VARIABLE} > value
    • ${VARIABLE} >= value
    • ${VARIABLE} in (a, b) # short for ${VARIABLE} == a or ${VARIABLE} == b
    • ${VARIABLE} ~ REGEX # python regexp: re.search(REGEX, ${VARIABLE}) != None
    • ${VARIABLE} !~ REGEX # negated regexp match
  • And rule: [some condition] and [some other condition]
  • Or rule: [some condition] or [some other condition]
  • Not rule: not ([some condition])
  • Implication rule: [some condition] ==> [some condition]
  • Equivalence rule: [some condition] <==> [some condition]
  • [some condition]: Variable condition OR (rule)

Rules can be used to remove variable combinations that should not be used in test generation.

An example of a valid rule line:

${VARIABLE_1} == Value 1  ==>  (${FOO} == bar  or  ${FOO} == zoo)

Which means: When ${VARIABLE_1} value is "Value 1" then ${FOO} should either be "bar" or "zoo".

State blocks should be next. First state block is the starting state.

State block starts with a line containing the states name. Valid state name contains only upper and lowercase characters a-zA-Z, numbers (not at the start) 0-9 and spaces (not at the start or end and only one between words).

This is followed by the Robot Framework steps that should be executed when in that state.

This can be followed by an actions block definition.

An actions block starts with [Actions] tag and is followed by one or more action lines.

An action line has four parts:

  • A Robot Framework step that is executed when the action happens (action label) (you can also leave this out - use a tau transition)
  • ==> right arrow with two spaces before and after
  • Name of the state that the machine ends up when the action is taken (end state)
  • Optional rule (when the action is available) this either starts with when and the rule or otherwise - meaning this action should be taken when all of the other actions with same action label are not available

An example of a valid state definition::

State Name
  Robot Framework  Step  with  ${arguments}
  Log  something  WARN
  [Actions]
    Log  other thing  ==>  Other State  when  ${FOO} == bar
    Log  other thing  ==>  Another State  when  (${FOO} == zoo  and  ${BAR} == goo)
    Log  other thing  ==>  End State  otherwise
    Log  nothing      ==>  End State
    ==>  Some state # This here is a tau transition that does not write a step to the test

robomachine's People

Contributors

bjornfor avatar davidkaplansweden avatar glmeece avatar handitover avatar marc- avatar mkorpela avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

robomachine's Issues

Any of list

Is it possible to provide a list for "any of", and create test cases according to list length?

${USERNAME}  any of  @{LIST}  

Result variable

Variable that is defined from the values of the other variables

${RESULT} := FOO when condition
BAR when condition2

Installation fails

RoboMachine installation via pip (within virtualenv) fails due to missing dependencies.

Downloading/unpacking RoboMachine
  Downloading RoboMachine-0.7.tar.gz
  Running setup.py (path:/tmp/pip-build-THNdGc/RoboMachine/setup.py) egg_info for package RoboMachine
    Traceback (most recent call last):
      File "<string>", line 17, in <module>
      File "/tmp/pip-build-THNdGc/RoboMachine/setup.py", line 6, in <module>
        import robomachine
      File "robomachine/__init__.py", line 16, in <module>
        from parsing import parse
      File "robomachine/parsing.py", line 15, in <module>
        from pyparsing import *
    ImportError: No module named pyparsing
    Complete output from command python setup.py egg_info:
    Traceback (most recent call last):

  File "<string>", line 17, in <module>

  File "/tmp/pip-build-THNdGc/RoboMachine/setup.py", line 6, in <module>

    import robomachine

  File "robomachine/__init__.py", line 16, in <module>

    from parsing import parse

  File "robomachine/parsing.py", line 15, in <module>

    from pyparsing import *

ImportError: No module named pyparsing

See
https://github.com/mkorpela/RoboMachine/blob/master/setup.py#L6
https://github.com/mkorpela/RoboMachine/blob/master/setup.py#L13

Proposal:
version needs to be moved into seprate module without external dependencies.

Order of rules matter

I was under the impression that the order of the rules didn't matter. Apparently not. At least if the rules somewhat intersect.

Try swapping the two constraints below and watch how the generated file contains one more/less test.

*** Machine ***
${NAME}    any of    Adam    Peter
${LAST_NAME}    any of    Smith    Brown    Johnson

${LAST_NAME} == Smith  ==>  ${NAME} == Adam
${NAME} == Peter  ==>  ${LAST_NAME} == Brown

Data driven
    Test Driver

*** Keywords ***
Test Driver
    Log To Console    \n${NAME} ${LAST_NAME}

getting this error when trying to create JSON in robot file

Exception at line 20
Expected Re:('\w+( \w+)*')
line: "${NAME} any of ${NAME} ${NAME1} ${NAME2} ${NAME3} ${NAME4} ${NAME5}"

Code below ๐Ÿ‘
*** Settings ***
Library Collections
Library json

*** Variables ***
${NAME} XXXX
${ID} YYYY
${NAME1} QQQQ
${ID1} WWWW
${NAME2} EEEE
${ID2} RRRR
${NAME3} TTTT
${ID3} YYYY
${NAME4} UUUU
${ID4} IIII
${NAME5} OOOO
${ID5} PPPP

*** Machine ***
${NAME} any of ${NAME} ${NAME1} ${NAME2} ${NAME3} ${NAME4} ${NAME5}
${ID} any of ${ID} ${ID1} ${ID2} ${ID3} ${ID4} ${ID5}

*** Test Cases ***
Test Create Json
${req_dict} Create Dictionary name=${NAME} id=${ID}
${req_json} Json.Dumps ${req_dict}
Log To Console *** Test Create Json Result ***
Log To Console ${req_json}

*** Keywords ***
Prepare Json Keyword
[Arguments] @{args}
${req_dict} Create Dictionary @{args}
${req_json} Json.Dumps ${req_dict}
[Return] ${req_json}

Two different 0.7 tags in repo

Was it intentional to have both '0.7' and 'v0.7' tags in repo?

$ git tag
0.2
0.5
0.6
0.7
v0.7

I was expecting the next tag to be '0.8'.

Tests fail with pyparsing >= 3

RoboMachine fails to build in https://github.com/nixos/nixpkgs ever since pyparsing was upgraded from 2.4.7 to 3.0.6 (due to some tests failing):

[...]
ERROR: test_generate_random_with_variable_resolving_problem (robomachine.test.robomachina_test.TestTestGeneration)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "/build/RoboMachine-0.9.0/robomachine/parsing.py", line 216, in parse
    return machine.parseString(resolve_whitespace(text), parseAll=True)[0]
  File "/nix/store/rv3dbmbbb7h9x1rs488fq4d2d0p9cngg-python3.9-pyparsing-3.0.6/lib/python3.9/site-packages/pyparsing/core.py", line 1127, in parse_string
    raise exc.with_traceback(None)
pyparsing.exceptions.ParseException: Expected {Re:(' *\n') ^ LineEnd}, found '$'  (at char 16), (line:2, col:1)

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/build/RoboMachine-0.9.0/robomachine/test/robomachina_test.py", line 271, in test_generate_random_with_variable_resolving_problem
    m = robomachine.parse(_VAR_PROBLEM_MACHINE)
  File "/build/RoboMachine-0.9.0/robomachine/parsing.py", line 221, in parse
    raise RoboMachineParsingException(pe.msg)
robomachine.parsing.RoboMachineParsingException: Expected {Re:(' *\n') ^ LineEnd}

----------------------------------------------------------------------
Ran 72 tests in 0.659s

FAILED (errors=10)
Test failed: <unittest.runner.TextTestResult run=72 errors=10 failures=0>
error: Test failed: <unittest.runner.TextTestResult run=72 errors=10 failures=0>
builder for '/nix/store/hlp1hwf16nbnjvr5vdx03b497kq7xijj-python3.9-RoboMachine-0.9.0.drv' failed with exit code 1

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.