Skip to content

Creating custom Actions

igorsantos07 edited this page Dec 22, 2010 · 13 revisions

Pyccuracy comes with dozens of pre-defined actions to do many kinds of simple things like clicking on buttons, filling forms, navigating and so on.

You may also want to write your own custom Actions for many reasons:

  • Improve the readability of your tests;
  • Reuse of test code;
  • Synthesize pre-conditions (like the example below);
  • Do complex setups;
  • … and virtually anything that you could do with Python/Pyccuracy code.

For instance, suppose that you want to write a custom action that will be a pre-condition (Given statement) to be used in some of your tests that require a user to be logged in into the system, like this example:

As a user
I want to be able to search
So that I can find interesting content

Scenario 1 - Logged in search
Given
    I am logged in with username "test_account" and password "test"
    And I go to "/search.html"
When
    I see "search field" textbox
    And I fill "search field" textbox with "pyccuracy rocks"
    And I click "search" button and wait
Then
   I see "Search for pyccuracy rocks - My cool website" title

The following action is not bundled with Pyccuracy but you can easily implement it:

I am logged in with username "test_account" and password "test"

To do that, you will need to:

1) Implement a class that inherits from ActionBase

from pyccuracy.actions import ActionBase

class LoggedInAction(ActionBase):
    pass

2) Define the regular expression that will match your custom Action

from pyccuracy.actions import ActionBase

class LoggedInAction(ActionBase):
    regex = r'^(And )?I am logged in with username [\"](?P<username>.+)[\"] and password [\"](?P<password>.+)[\"]$'

3) Implement the execute method

Implement the execute method receiving the Pyccuracy context and the variables you defined in your regular expression as parameters (in this case, username and password):

from pyccuracy.actions import ActionBase

class LoggedInAction(ActionBase):
    regex = r'^(And )?I am logged in with username [\"](?P<username>.+)[\"] and password [\"](?P<password>.+)[\"]$'

    def execute(self, context, username, password):
        pass

4) Implement the Action

To finish, we will tell Pyccuracy to execute some regular actions inside the method body, to login into the website with the username and password informed in the test:

from pyccuracy.actions import ActionBase

class LoggedInAction(ActionBase):
    regex = r'^(And )?I am logged in with username [\"](?P<username>.+)[\"] and password [\"](?P<password>.+)[\"]$'

    def execute(self, context, username, password):
        self.execute_action(u"I go to \"/index.html\"", context)

        # if the user is not logged in already, we do the login process
        logged_in = False
        try:
            self.execute_action(u"And I see \"already have an account? sign in\" link", context)
        except ActionFailedError:
            logged_in = True

        if not logged_in:
            self.execute_action(u"And I click \"already have an account? sign in\" link", context)
            self.execute_action(u"And I wait for the page to load for 5 seconds", context)
            self.execute_action(u"And I fill \"username\" textbox with \"%s\"" % username, context)
            self.execute_action(u"And I fill \"password\" textbox with \"%s\"" % password, context)
            self.execute_action(u"And I click \"sign in\" button", context)

You can see that the LoggedInAction custom Action is just executing some of the pre-defined actions and a little bit of Python checking. You can create Actions that don’t receive any parameters, that execute just Pyccuracy Actions or that execute just vanilla Python code. You can do whatever you need for your Action.

5) Multiple Step Arguments

This feature comes from the way Cucumber does multiple step arguments.

If the regular expression for your action ends with ‘:’, then you can add arguments to it like this:

And I see "some" table as:
    | Name   | Age  | Sex  |
    | John   | 28   | Male | 
    | Paul   | 30   | Male |

What happens behind the curtains is that Pyccuracy detects that the first line of your action matches a regular expression for a registered action AND that it ends with ‘:’. Now Pyccuracy adds to a Table object all the other rows.

In the above scenario, Pyccuracy would feed your custom action a table argument with the following Python object:

[{'Name':'John', 'Age':'28', 'Sex':'Male'}, {'Name':'Paul', 'Age':'30', 'Sex':'Male'}]

This allows your action to do anything it needs to with this info. A good example would be something like:

Given
    I have the following registered users:
        | name  | password    | email               |
        | John  | 12345       | john@mycompany.org  |
        | Paul  | 67890       | paul@mycompany.org  |

Please note that I only indent the pipe (‘|’) characters for readability, since Pyccuracy won’t care for the whitespace to the right or to the left.

This action could be implemented as follows:

class RegisterUsers(ActionBase):
    regex = r'^(And )?I have the following registered users:$'

    def execute(self, context, table):
        for user in table:
            #saves user using user['name'], user['password'] and user['email']

It’s really important to acknowledge that the table argument must be named like that, since it’s injected by Pyccuracy.

This allows you to have a VERY extensible way of using your domain model in your acceptance tests.

6) Using the custom Actions

Just put the custom Action code in a .py file (in this case I would create a “login_action.py” file) and put the file in the same directory your tests are. When you execute your tests, Pyccuracy will look for custom Actions in the tests directory before executing them.

For organization sake, you may want to put your actions in a separate dir. If you want to do that, when you call pyccuracy_console inform the -A parameter, that is the directory where the custom Actions are:

$ pyccuracy_console -A tests/acceptance/actions