[melbourne-pug] Thanks for doing MPUG last night

Jason King pizza at netspace.net.au
Sun Sep 14 15:33:47 CEST 2014


On 11/09/14 17:56, Andy Kitchen wrote:
> I just haven't had time to put my code online yet
> (sorry! I will soon, really) but in the mean time here are some links.
>

er, yes, I've been slack too, sorry about that.

Here's the test of the talk I gave, I tried doing in it ipython notebook 
format,
I'm not convinced it worked that well for me, but here it is.

as I mentioned at the time, its only for chrome, I didn't get a chance 
to get it
running for any other browser.
-------------- next part --------------
{
 "metadata": {
  "celltoolbar": "Raw Cell Format",
  "name": "",
  "signature": "sha256:77836ec87db745631fef01ab82a6f5d7c8c12aae2ff5061a222082983a5acca9"
 },
 "nbformat": 3,
 "nbformat_minor": 0,
 "worksheets": [
  {
   "cells": [
    {
     "cell_type": "heading",
     "level": 1,
     "metadata": {},
     "source": [
      "Oh, Behave Yourself."
     ]
    },
    {
     "cell_type": "markdown",
     "metadata": {},
     "source": [
      "\n",
      "How to get behave tests to run selenium code to test your web sites.\n",
      "\n",
      "\n",
      "\n",
      "\n",
      "\n",
      "\n",
      "\n",
      "\n",
      "\n",
      "\n",
      "\n",
      "\n",
      "\n",
      "\n",
      "\n",
      "\n",
      "\n",
      "\n",
      "\n",
      "\n",
      "\n",
      "\n"
     ]
    },
    {
     "cell_type": "markdown",
     "metadata": {},
     "source": [
      "Behave is fairly well decumented, as is selenium.  Getting the two to play well with each other was a bit more difficult, \n",
      "and required checking and experimenting with multiple sources of info to make it work.  Here's basically what I did to make it go.\n",
      "\n",
      "      "
     ]
    },
    {
     "cell_type": "code",
     "collapsed": false,
     "input": [
      "Behave:\n",
      "    \n",
      "    Behave is a framework to create and run python tests in a way that lets the \n",
      "    testers write tests in the language they know best, and the coders implementing \n",
      "    the tests create the code in their favourite language as well.\n",
      "    \n",
      "    \n",
      "    Tests are written like this:\n",
      "        \n",
      "    Given the current state of the program,\n",
      "    When the user does something,\n",
      "    And the user actually turned the power on,\n",
      "    Then test to make sure that the program worked,\n",
      "    And print out a result.\n",
      "    \n",
      "    Its the coders job to turn the text into this:\n",
      "    \n",
      "    Given the current state of the program\n",
      "    When the user does something\n",
      "    When the user actually turned the power on\n",
      "    Then test to make sure that the program worked\n",
      "    Then print out a result\n",
      "    \n",
      "    So replace \"And\" with the word above it (Given , When or Then)\n",
      "    remove punctuation\n",
      "    \n",
      "    The coder then create python tests that look like this:\n",
      "        \n",
      "    \n",
      "@given('the current state of the program')\n",
      "def step_impl(context):\n",
      "    #either write some code to test that you're in the expected state, or \n",
      "    assert(True)\n",
      "\n",
      "@when('the user does something')\n",
      "def step_impl(context):\n",
      "    #write some code here to either press a key, or click the mouse on a control\n",
      "    pass    \n",
      "        \n",
      "        \n",
      "@then('test to make sure that the program worked')\n",
      "def step_impl(context):\n",
      "    assert the_expected_result_happened\n",
      "    \n",
      "\n",
      "@then('print out a result')\n",
      "def step_impl(context):\n",
      "    assert value_appears_on_the_screen\n",
      "        "
     ],
     "language": "python",
     "metadata": {},
     "outputs": []
    },
    {
     "cell_type": "code",
     "collapsed": false,
     "input": [
      "Install behave and selenium into your environment\n",
      "\n",
      "pip install behave\n",
      "pip install selenium\n",
      "\n",
      "Download the chrome webdriver\n",
      "http://chromedriver.storage.googleapis.com/index.html?path=2.9/\n",
      "And place it in your $PATH (or %PATH% )\n",
      "    \n",
      "Note that at the time of writing, chrome webdriver 2.10 didn't work with the most recent chrome release on linux, so 2.9 was used."
     ],
     "language": "python",
     "metadata": {},
     "outputs": []
    },
    {
     "cell_type": "heading",
     "level": 2,
     "metadata": {},
     "source": [
      "Create the following directory structure"
     ]
    },
    {
     "cell_type": "raw",
     "metadata": {},
     "source": [
      "Tests\n",
      "\u251c\u2500\u2500 features\n",
      "\u2502\u00a0\u00a0 \u251c\u2500\u2500 environment.py\n",
      "\u2502\u00a0\u00a0 \u251c\u2500\u2500 path1a.feature\n",
      "\u2502\u00a0\u00a0 \u251c\u2500\u2500 path1d.feature\n",
      "\u2502\u00a0\u00a0 \u251c\u2500\u2500 path1e.feature\n",
      "\u2502\u00a0\u00a0 \u2514\u2500\u2500 steps\n",
      "\u2502\u00a0\u00a0     \u2514\u2500\u2500 steps.py\n",
      "\u2514\u2500\u2500 readme.txt   (instructions for new people)\n",
      "\n"
     ]
    },
    {
     "cell_type": "raw",
     "metadata": {},
     "source": [
      "Create your behave tests\n",
      "\n",
      "Feature: test path 1a\n",
      "\n",
      "  Scenario: Choose appointment date then doctor, then register, then make appointment for sel\n",
      "    Given user is on appointment page\n",
      "    When the user selects a date\n",
      "    Then the doctors list filters for availability\n",
      "    And the appointment list filters for availability\n",
      "    When the user selects a doctor\n",
      "    Then the available times are displayed\n",
      "    When the user selects a time\n",
      "    And the user selects next\n",
      "    Then the Login/register modal appears\n",
      "    When the user selects register\n",
      "    Then the registration modal is displayed\n",
      "    When the user fills in the details\n",
      "    And the user clicks next\n",
      "    Then the registration details are verified\n",
      "    And the registration details are written to the database\n",
      "    And the Appointment Confirmation modal is shown with user as default patient\n",
      "    When user clicks confirm\n",
      "    Then the appointment is written to database\n",
      "    And the main modal is shown\n",
      "\n"
     ]
    },
    {
     "cell_type": "heading",
     "level": 2,
     "metadata": {},
     "source": [
      "Environment.py"
     ]
    },
    {
     "cell_type": "code",
     "collapsed": false,
     "input": [
      "import threading\n",
      "from wsgiref import simple_server\n",
      "from selenium import webdriver\n",
      "#from my_application import model\n",
      "#from my_application import web_app\n",
      "\n",
      "\n",
      "def before_all(context):\n",
      "    context.server = simple_server.WSGIServer(('', 8000))\n",
      "    context.server.set_app(web_app.main(environment='test'))\n",
      "    context.thread = threading.Thread(target=context.server.serve_forever)\n",
      "    context.thread.start()\n",
      "    context.browser = webdriver.Chrome()\n",
      "\n",
      "def after_all(context):\n",
      "    context.server.shutdown()\n",
      "    context.thread.join()\n",
      "    context.browser.quit()\n",
      "\n",
      "def before_feature(context, feature):\n",
      "    #model.init(environment='test')\n",
      "    pass"
     ],
     "language": "python",
     "metadata": {},
     "outputs": []
    },
    {
     "cell_type": "heading",
     "level": 2,
     "metadata": {},
     "source": [
      "Feature"
     ]
    },
    {
     "cell_type": "code",
     "collapsed": false,
     "input": [
      "Feature: test path 1a\n",
      "\n",
      "  Scenario: Choose appointment date then doctor, then register, then make appointment for sel\n",
      "    Given user is on appointment page\n",
      "    When the user selects a date\n",
      "    Then the doctors list filters for availability\n",
      "    And the appointment list filters for availability\n",
      "    When the user selects a doctor\n",
      "    Then the available times are displayed\n",
      "    When the user selects a time\n",
      "    And the user selects next\n",
      "    Then the Login/register modal appears\n",
      "    When the user selects register\n",
      "    Then the registration modal is displayed\n",
      "    When the user fills in the details\n",
      "    And the user clicks next\n",
      "    Then the registration details are verified\n",
      "    And the registration details are written to the database\n",
      "    And the Appointment Confirmation modal is shown with user as default patient\n",
      "    When user clicks confirm\n",
      "    Then the appointment is written to database\n",
      "    And the main modal is shown\n"
     ],
     "language": "python",
     "metadata": {},
     "outputs": []
    },
    {
     "cell_type": "code",
     "collapsed": false,
     "input": [
      "Finding the right element on the page\n",
      "\n",
      "find_elements_by_class_name()\n",
      "find_element_by_xpath()\n",
      "find_elements_by_id()\n",
      "\n",
      "see http://selenium-python.readthedocs.org/en/latest/locating-elements.html for more"
     ],
     "language": "python",
     "metadata": {},
     "outputs": []
    },
    {
     "cell_type": "heading",
     "level": 2,
     "metadata": {},
     "source": [
      "XPATH"
     ]
    },
    {
     "cell_type": "raw",
     "metadata": {},
     "source": [
      "\n",
      "\n",
      "see http://selenium-python.readthedocs.org/en/latest/locating-elements.html , it has a short and sweet intro to xpath\n",
      "\n",
      "\n",
      "Suggested browser plugins to help you generate and test xpath queries are:\n",
      "    Chrome\n",
      "        XPath Helper 1.0.13  https://chrome.google.com/webstore/detail/xpath-helper/hgimnogjllphhhkhlmebbmlgjoejdpjl\n",
      "        Ctrl-Shift X to turn on, hold down shift as you move the mouse to see the XPath query for what is under the mouse\n",
      "    Firefox ?"
     ]
    },
    {
     "cell_type": "heading",
     "level": 2,
     "metadata": {},
     "source": [
      "tests.py"
     ]
    },
    {
     "cell_type": "code",
     "collapsed": false,
     "input": [
      "from behave import *\n",
      "import selenium\n",
      "from selenium import webdriver\n",
      "from selenium.common.exceptions import NoSuchElementException\n",
      "\n",
      "test_url = 'http://localhost:8011/'\n",
      "\n",
      "@given('a suitable date')\n",
      "# td class=\"bookday month-1 available\" data-date=\"30-06-2014\"\n",
      "def step_impl(context):\n",
      "    try:\n",
      "        h = context.browser.find_elements_by_class_name('available')\n",
      "        ok_(len(h) > 0)\n",
      "    except NoSuchElementException:\n",
      "        return False\n",
      "\n",
      "@given('a list of doctors')\n",
      "#how should I grab this, the list from the calendar page?\n",
      "# <ul data-bind=\"foreach: $root.doctors\">\n",
      "#\n",
      "def step_impl(context):\n",
      "    pass\n",
      "\n",
      "@given('when login is pressed, we dont have a username and password')\n",
      "#no user? .  check username and password fields in form to make sure they're empty?\n",
      "def step_impl(context):\n",
      "    pass\n",
      "\n",
      "def step_impl(context):\n",
      "    try:\n",
      "        h = context.browser.find_element_by_class_name('time')\n",
      "        return True\n",
      "    except NoSuchElementException:\n",
      "        return False\n",
      "\n",
      "@when('the login link is clicked')\n",
      "#click the login button\n",
      "def step_impl(context):\n",
      "    login_link = context.browser.get_element(context.browser, tag='login')\n",
      "    webdriver.ActionChains(context.browser).move_to_element(login_link).click(login_link).perform()\n",
      "\n",
      "@then('choose a doctor')\n",
      "#click on a doctor (pass a name in, or click one at random ?)\n",
      "#there's a function to get all elements with a certain property, use that if you need a random link\n",
      "def step_impl(context):\n",
      "    login_link = context.browser.get_element(context.browser, tag='doctorlink')\n",
      "    webdriver.ActionChains(context.browser).move_to_element(login_link).click(login_link).perform()\n",
      "    #assert context.failed is False\n",
      "\n",
      "@then('enter in our details, and then press OK')\n",
      "#cycle through form fields, enter details, then press ok\n",
      "def step_impl(context):\n",
      "    assert False\n",
      "\n",
      "@given('user is on appointment page')\n",
      "#make sure user can see the appointments page (not necessarily see appointments)\n",
      "def step_impl(context):\n",
      "    context.browser.get(test_url)\n",
      "    assert(True)\n",
      "\n",
      "@when('the user selects a date')\n",
      "def step_impl(context):\n",
      "    try:\n",
      "        h = context.browser.find_element_by_xpath(\"//div[@class='times-grid']/div/a\")\n",
      "        webdriver.ActionChains(context.browser).move_to_element(h).click(h).perform()\n",
      "    except NoSuchElementException:\n",
      "        assert False\n",
      "\n",
      "@then('the doctors list filters for availability')\n",
      "#possible things happen here, someone in the list is unavailable?\n",
      "#one person is still available?\n",
      "def step_impl(context):\n",
      "    pass\n",
      "\n",
      "@then('the appointment list filters for availability')\n",
      "#not sure about this, some times may disappear\n",
      "def step_impl(context):\n",
      "    pass\n",
      "\n",
      "@when('the user selects a doctor')\n",
      "def step_impl(context):\n",
      "    try:\n",
      "        h = context.browser.find_element_by_xpath(\"//li[@class='available']\")\n",
      "        webdriver.ActionChains(context.browser).move_to_element(h).click(h).perform()\n",
      "    except NoSuchElementException:\n",
      "        assert False\n",
      "\n",
      "@then('the available times are displayed')\n",
      "#can see appointments  (what if there's no available times?  should //a be removed)\n",
      "def step_impl(context):\n",
      "    try:\n",
      "        h = context.browser.find_element_by_xpath(\"//div[@class='times-grid']//a\")\n",
      "        assert True\n",
      "    except NoSuchElementException:\n",
      "        assert False\n",
      "\n",
      "@When('the user selects a time')\n",
      "#user clicks on an appointment (at random?)\n",
      "def step_impl(context):\n",
      "    try:\n",
      "        h = context.browser.find_element_by_xpath(\"//div[@class='times-grid']//a\")\n",
      "        webdriver.ActionChains(context.browser).move_to_element(h).click(h).perform()\n",
      "        assert True\n",
      "    except NoSuchElementException:\n",
      "        assert False\n",
      "\n",
      "@When('the user selects next')\n",
      "#find \"next\" and click on it.  I'm guessing \"next\" is the submit button to a form.\n",
      "#if not, well, find the link and click on it\n",
      "def step_impl(context):\n",
      "    try:\n",
      "        h = context.browser.find_element_by_xpath(\"//div[@class='submit']//a[@class='btn btn-primary']\")\n",
      "        webdriver.ActionChains(context.browser).move_to_element(h).click(h).perform()\n",
      "        assert True\n",
      "    except NoSuchElementException:\n",
      "        assert False\n",
      "\n",
      "\n",
      "\n",
      "@Then('the Login/register modal appears')\n",
      "#check for login/register\n",
      "def step_impl(context):\n",
      "    try:\n",
      "        form = context.browser.find_element_by_id('form')\n",
      "        ok_(form.text.startswith(\"login\"),\n",
      "           'No login form %r' % h.text)\n",
      "    except NoSuchElementException:\n",
      "        return False\n",
      "\n",
      "\n",
      "@When('the user selects register')\n",
      "#user clicks on register link\n",
      "def step_impl(context):\n",
      "    try:\n",
      "        register_link = context.browser.find_element_by_class_name('register')\n",
      "        webdriver.ActionChains(context.browser).move_to_element(register_link).click(register_link).perform()\n",
      "        return True\n",
      "    except NoSuchElementException:\n",
      "        return False\n",
      "\n",
      "@Then('the registration modal is displayed')\n",
      "#make sure the registration form appears\n",
      "def step_impl(context):\n",
      "    try:\n",
      "        form = context.browser.find_element_by_xpath(\"//form[@id='registerForm']\")\n",
      "        return True\n",
      "    except NoSuchElementException:\n",
      "        assert False\n",
      "\n",
      "@When('the user fills in the details')\n",
      "#cycle through the form and fill in the details\n",
      "def step_impl(context):\n",
      "    pass\n",
      "\n",
      "@When('the user clicks next')\n",
      "#see 'the user selects next'\n",
      "def step_impl(context):\n",
      "    try:\n",
      "        form = context.browser.find_element_by_class_name('form')\n",
      "        form,submit()\n",
      "        return True\n",
      "    except NoSuchElementException:\n",
      "        return False\n",
      "\n",
      "@Then('the registration details are verified')\n",
      "#whats verifying the details?  javascript? the PMS ?\n",
      "def step_impl(context):\n",
      "    pass\n",
      "\n",
      "@Then('the registration details are written to the database')\n",
      "#make sure registration details can be accessed from the django ORM\n",
      "def step_impl(context):\n",
      "    pass\n",
      "\n",
      "@Then('the Appointment Confirmation modal is shown with user as default patient')\n",
      "def step_impl(context):\n",
      "    try:\n",
      "        confirm = context.browser.find_element_by_xpath(\"//*[contains(text(), 'Appointment Details')]\")\n",
      "        assert True\n",
      "    except NoSuchElementException:\n",
      "        assert False\n",
      "\n",
      "\n",
      "@When('user clicks confirm')\n",
      "#find \"confirm\" and click on it\n",
      "def step_impl(context):\n",
      "    try:\n",
      "        confirm = context.browser.find_element_by_xpath(\"//*[contains(text(), 'Confirm Appointment')]\")\n",
      "        webdriver.ActionChains(context.browser).move_to_element(confirm).click(confirm).perform()\n",
      "    except NoSuchElementException:\n",
      "        assert False\n",
      "\n",
      "@Then('the appointment is written to database')\n",
      "#make sure the apointment you just made is accessable from the django ORM\n",
      "def step_impl(context):\n",
      "    assert True\n",
      "\n",
      "@Then('the main modal is shown')\n",
      "#whats \"the main modal\"?\n",
      "def step_impl(context):\n",
      "    assert False\n",
      "\n",
      "@when('the user selects log in')\n",
      "#find \"log in\" and click on it\n",
      "def step_impl(context):\n",
      "    try:\n",
      "        login = context.browser.find_element_by_xpath(\"//*[contains(text(), 'Log In')]\")\n",
      "        webdriver.ActionChains(context.browser).move_to_element(login).click(login).perform()\n",
      "    except NoSuchElementException:\n",
      "        assert False\n",
      "\n",
      "@then('the login modal is displayed')\n",
      "#login form is displayed\n",
      "def step_impl(context):\n",
      "    try:\n",
      "        confirm = context.browser.find_element_by_xpath(\"//*[contains(text(), 'Sign in')]\")\n",
      "        assert True\n",
      "    except NoSuchElementException:\n",
      "        assert False\n",
      "\n",
      "\n",
      "@when('the user fills in username and password')\n",
      "#cycle through the login form and fill in the details\n",
      "def step_impl(context):\n",
      "    pass\n",
      "\n",
      "\n",
      "@then('Login details are verified')\n",
      "#the screen doesn't say \"login failed\"?\n",
      "def step_impl(context):\n",
      "    pass\n",
      "\n",
      "@then('the Appointment Confirmation modal is shown')\n",
      "def step_impl(context):\n",
      "    pass\n",
      "\n",
      "@when('the user selects a different name from the drop down list')\n",
      "def step_impl(context):\n",
      "    pass\n",
      "\n",
      "@when('the user clicks confirm')\n",
      "#find \"confirm\" and click on it\n",
      "def step_impl(context):\n",
      "    try:\n",
      "        confirm = context.browser.find_element_by_link_text('Confirm')\n",
      "        webdriver.ActionChains(context.browser).move_to_element(confirm).click(confirm).perform()\n",
      "    except NoSuchElementException:\n",
      "        assert False\n",
      "\n",
      "\n",
      "\n",
      "@then(u'the available dates are displayed')\n",
      "def step_impl(context):\n",
      "    assert False\n",
      "\n",
      "@when(u'the user fills in all details')\n",
      "def step_impl(context):\n",
      "    assert False\n",
      "\n",
      "@when(u'the user clicks login/register link on page')\n",
      "def step_impl(context):\n",
      "    assert False\n",
      "\n",
      "@when(u'the user selects My Account')\n",
      "def step_impl(context):\n",
      "    assert False\n",
      "\n",
      "@then(u'account details are shown')\n",
      "def step_impl(context):\n",
      "    assert False\n",
      "\n",
      "@when(u'the user selects New Patient')\n",
      "def step_impl(context):\n",
      "    assert False\n",
      "\n",
      "@when(u'the user enters new patient details')\n",
      "def step_impl(context):\n",
      "    assert False\n",
      "\n",
      "@when(u'the user clicks ok')\n",
      "def step_impl(context):\n",
      "    assert False\n",
      "\n",
      "@then(u'new patient data is verified')\n",
      "def step_impl(context):\n",
      "    assert False\n",
      "\n",
      "@then(u'new patient data is written to database')\n",
      "def step_impl(context):\n",
      "    assert False\n",
      "\n",
      "@when(u'the user closes the dialog box')\n",
      "def step_impl(context):\n",
      "    assert False\n",
      "\n",
      "@when(u'the user selects the new patient name from the drop down list')\n",
      "def step_impl(context):\n",
      "    assert False\n",
      "\n",
      "@then(u'the login details are verified')\n",
      "def step_impl(context):\n",
      "    assert False\n",
      "\n",
      "@when(u'the Appointment Confirmation modal is shown with user as default patient')\n",
      "def step_impl(context):\n",
      "    assert False\n"
     ],
     "language": "python",
     "metadata": {},
     "outputs": []
    },
    {
     "cell_type": "code",
     "collapsed": false,
     "input": [
      "Use behave -v to find out what behave is really doing, to find out why its not working"
     ],
     "language": "python",
     "metadata": {},
     "outputs": []
    },
    {
     "cell_type": "code",
     "collapsed": false,
     "input": [
      "Sources:\n",
      "    http://testingbot.com/support/getting-started/behave.html\n",
      "    http://selenium-python.readthedocs.org/en/latest/locating-elements.html   \n",
      "    StackOverflow\n",
      "        \n",
      "Thanks to:\n",
      "    Ed Schofield (for intro to behave)\n",
      "    Adrienne Walker (for writing the tests)"
     ],
     "language": "python",
     "metadata": {},
     "outputs": []
    }
   ],
   "metadata": {}
  }
 ]
}


More information about the melbourne-pug mailing list