Writing Scripts

Creating a new project

For starting a new project you have access to this command :

oct-newproject <project_name>

This command will create a new project inside the current directory named with the <project_name> argument

The created directory must look like this :

.
├── config.cfg
├── templates
│   ├── css
│   │   └── style.css
│   ├── footer.html
│   ├── head.html
│   ├── img
│   └── scripts
└── test_scripts
    └── v_user.py

This folders contains the basic for running an OCT project.

Configuration

For configuration explanation and examples see the Configuration page

Customizing your templates

You need an other render for the results ? the default template is ugly and you want to change it ? It’s ok, we have done some things for help you to do that.

If you have created your project with the oct-newproject command, you have a templates directory inside your project. This directory is used for writing the results, so each call to multimech-run command will read this files. With this you can easily update the template and customize it to fit your needs. It’s simple as that.

For the moment the templates can’t be fully modified, but you steel have plenty of options to change them.

Let’s take a look at the style.css file :

/* http://meyerweb.com/eric/tools/css/reset/
   v2.0 | 20110126
   License: none (public domain)
*/

html, body, div, span, applet, object, iframe,
h1, h2, h3, h4, h5, h6, p, blockquote, pre,
a, abbr, acronym, address, big, cite, code,
del, dfn, em, img, ins, kbd, q, s, samp,
small, strike, strong, sub, sup, tt, var,
b, u, i, center,
dl, dt, dd, ol, ul, li,
fieldset, form, label, legend,
table, caption, tbody, tfoot, thead, tr, th, td,
article, aside, canvas, details, embed,
figure, figcaption, footer, header, hgroup,
menu, nav, output, ruby, section, summary,
time, mark, audio, video {
    margin: 0;
    padding: 0;
    border: 0;
    font-size: 100%;
    font: inherit;
    vertical-align: baseline;
}
/* HTML5 display-role reset for older browsers */
article, aside, details, figcaption, figure,
footer, header, hgroup, menu, nav, section {
    display: block;
}
body {
    line-height: 1;
}
ol, ul {
    list-style: none;
}
blockquote, q {
    quotes: none;
}
blockquote:before, blockquote:after,
q:before, q:after {
    content: '';
    content: none;
}
table {
    border-collapse: collapse;
    border-spacing: 0;
}

body {
    background-color: #f4f4f4;
    font-family: "Helvetica Neue", Helvetica, Roboto, Arial, sans-serif;
}

h1  {
    font-size: 4em;
    background: #2b2b2b;
    color: white;
    font-weight: bold;
}

h2 {
    font-size: 2em;
    background: #f78930;
    margin: 15px 0 15px 0;
}

h1, h2, h3, h4, h5, h6 {
    padding: 15px;
}

h4 {
    font-weight: bold;
    font-size: 1.3em;
}

h3 {
    font-size: 1.5em;
    font-weight: bold;
}

.summary {
    padding-left: 15px;
}

.summary > b {
    font-weight: bold;
}

#main table {
    margin-left: 15px;
    border: 1px solid grey;
}

#main th {
    font-weight: bold;
    padding: 10px 0 10px 0;
    border: 1px solid grey;
}

#main tr {
    padding: 10px 0 10px 0;
    text-align: center;
}

#main td {
    min-width: 70px;
    padding: 10px 5px 10px 5px;
    border: 1px solid grey;
}

hr {
    color: #f4f4f4;
    background-color: #f4f4f4;
    border: none;
}

As you can see, all style present on the result page is here, so feel free to update it. But you may need some other css files, like a css framework, or even javascript files ? why not after all ?

Well you can do that, you can include all the files you need for customize your results page.

How ? simply edit the `templates/head.html’ and include your files, you can even create your own header, add messages at the top of the page, etc...

A little explanation of how this work :

When you call the multimech-run command inside your project directory, the command will look for the templates directory and read the head.html and the footer.html files, and will create a new html page with them. At the same time the command will copy all files insides the img, scripts, and css directories. So everything added in this folders will be in the associated result directory. In that way you can add all the stuff you want to your results, and not reworking each result after each test

Writing your first script

It’s time to write our first script and test it, so first let’s take a look at the generated v_user.py file :

from oct.core.generic import GenericTransaction
import random
import time
import os


CONFIG_PATH = os.path.join(os.path.dirname(os.path.abspath(__file__)), '../')


class Transaction(GenericTransaction):
def __init__(self):
    GenericTransaction.__init__(self, True, CONFIG_PATH)

def run(self):
    r = random.uniform(1, 2)
    time.sleep(r)
    self.custom_timers['Example_Timer'] = r


if __name__ == '__main__':
trans = Transaction()
trans.run()
print trans.custom_timers

So what does this script ? Since it’s an example script, actually it just sleep for 1 or 2 seconds.

Let’s update this script a little, but first don’t forget to update the configuration file to fit your configuration.

Okay so let’s write a simple script, just for accessing the index page of our web site and get the statics file of it

from oct.core.generic import GenericTransaction
import time
import os


CONFIG_PATH = os.path.join(os.path.dirname(os.path.abspath(__file__)), '../')


class Transaction(GenericTransaction):
    def __init__(self):
        GenericTransaction.__init__(self, True, CONFIG_PATH)

    def run(self):
        test_time = time.time()

        resp = self.open_url('/')

        self.custom_timers['test_time'] = time.time() - test_time


if __name__ == '__main__':
    trans = Transaction()
    trans.run()
    print trans.custom_timers

So that’s it, we just open the index url of the website (based on the base_url configuration variable)and get the response object returned by the open_url method, then set a `test_time’ timer.

So what does this test do ? well it accesses to the index page and retrieve all css, javascript and img files in it. Simple as this

Testing your script

So what’s next ? Now you got your basic script retrieving your index page and associated statics files. But does it works ?

Let’s figure it out. To test your script 1 time, just to make sure all code work, you actually call the script with your python interpreter like this :

python my_script.py

With the previous script, if everything is ok, you must see the timer on the standard output.

Everything work find ? Nice, let’s now run our tests with lot of users, so update your configuration file and then you just have to run :

multimech-run <myproject>

Or if you’re already inside the path of you’re project, simply run :

multimech-run .

You must see the progress bar appears, you now just have to wait till the tests end. This action will create a results directory inside your project folder, and a sub-directory containing the results in csv or html format.

Handle forms

You now know how to access url and retrieve statics files, but this still basics actions right ? Let’s handles some forms and submit some data.

So we gonna take our previous script and update it a bit :

from oct.core.generic import GenericTransaction
from oct.testing.content import must_contain
import time
import os


CONFIG_PATH = os.path.join(os.path.dirname(os.path.abspath(__file__)), '../')


class Transaction(GenericTransaction):
    def __init__(self):
        GenericTransaction.__init__(self, True, CONFIG_PATH)

    def run(self):
        test_time = time.time()

        # getting the url
        resp = self.open_url('/showcase/index')

        # now we getting the form, using css selector
        self.get_form(selector='#searchForm')

        # we now have two properties for handling the form
        # self.br.form, containing the lxml for object
        # self.br.form_data, a dict containing all fields and values
        # let's just set the value and submit it
        self.br.form_data['q'] = 'test'

        # getting the response
        resp = self.br.submit_form()

        # checking response content
        must_contain(resp, 'Results that must be found')

        self.custom_timers['test_time'] = time.time() - test_time


if __name__ == '__main__':
    trans = Transaction()
    trans.run()
    print trans.custom_timers

We removed statics management for tests. So what do we do now ? Well let’s resume that :

  • access the index url
  • getting the form with id attribute set to searchForm
  • considering this form has 1 input named q, we set the data for this field to test
  • submit the form
  • checking the content of the returned page.

And that’s all, we handle a simple search form, and checking the results !