john pfeiffer
  • Home
  • Categories
  • Tags
  • Archives

selenium integration tests

import os
import sys
import time
import random
import string
import logging

from junit_xml import TestSuite, TestCase       # supports more generic conversion than unittest-xml-reporting

from SeleniumTest import SeleniumTest           # separate the low level driver details



class IntegrationTests( object ):


    def __init__( self, fqdn, selenium_wrapper ):
        self.selenium_wrapper = selenium_wrapper
        self.fqdn = fqdn
        self.base_url = 'https://' + self.fqdn
        self.group_name = str( int( time.time() ) )
        self.users = list()                                                     # list of tuples (email, user name)
        self.admin_email = 'admin-' + self.group_name + '@' + self.fqdn         # must be unique
        self.admin_password = 'mypassword'
        self.emoticon_file_name = 'shelby-emoticon.png'


    def test_sign_up( self ):
        logging.debug( 'DEBUG: creating account: ' + self.group_name )             # must be unique
        logging.debug( 'DEBUG: creating first user: ' + self.admin_email + ' with password: ' + self.admin_password )
        self.selenium_wrapper.sign_up( self.base_url, self.group_name, email=self.admin_email, password=self.admin_password )
        self.selenium_wrapper.assert_name_is_present( 'email[0]' )
        self.selenium_wrapper.assert_name_is_present( 'name[0]' )
        self.selenium_wrapper.assert_id_is_present( 'invite_link' )
        self.selenium_wrapper.assert_link_text_is_present( 'Skip this step' )
        self.selenium_wrapper.assert_id_is_present( 'next' )
        self.users.append( (self.admin_email, 'admin user') )


    def test_sign_in_admin( self ):
        # Assumes account and user are created
        self.selenium_wrapper.sign_out( self.base_url )
        self.selenium_wrapper.sign_in( self.base_url, self.admin_email, self.admin_password )
        self.selenium_wrapper.assert_is_equal( self.base_url + '/home' , self.selenium_wrapper.show_current_url() )
        self.selenium_wrapper.assert_link_text_is_present( 'Launch the web app' )
        self.selenium_wrapper.assert_css_selector_is_present( 'a.admin > span' )        # admin tab == privileges


    def test_add_user( self ):
        # Assumes account and user are created
        self.selenium_wrapper.sign_out( self.base_url )
        self.selenium_wrapper.sign_in( self.base_url, self.admin_email, self.admin_password )

        self.selenium_wrapper.assert_css_selector_is_present( 'a.admin > span' )        # admin tab == privileges
        self.selenium_wrapper.find_by_css_selector( 'a.admin > span' ).click( )
        self.selenium_wrapper.assert_is_equal( self.base_url + '/admin', self.selenium_wrapper.show_current_url() )
        self.selenium_wrapper.assert_link_text_is_present( 'Users' )

        logging.debug( 'DEBUG: listing users, asserting the admin is present' )
        self.selenium_wrapper.find_by_link_text( 'Users' ).click()
        self.selenium_wrapper.assert_is_equal( self.base_url + '/admin/users', self.selenium_wrapper.show_current_url() )
        self.selenium_wrapper.assert_css_selector_is_present( 'span[title="' + self.admin_email + '"]' )


        new_user_lastname = str( int( time.time( ) ) )
        new_user_name = 'user ' + new_user_lastname
        new_user_email = new_user_lastname + '@' + self.fqdn
        logging.debug( 'DEBUG: adding a user: ' + new_user_name + ' ' + new_user_email )

        self.selenium_wrapper.assert_is_equal( '+ Add user', self.selenium_wrapper.find_by_css_selector( 'input.silver' ).get_attribute( 'value' ) )
        self.selenium_wrapper.find_by_css_selector( 'input.silver' ).click()
        self.selenium_wrapper.assert_is_equal( self.base_url + '/admin/user', self.selenium_wrapper.show_current_url() )
        self.selenium_wrapper.add_user( new_user_name, new_user_email )
        self.selenium_wrapper.assert_is_equal( 'Added user ' + new_user_name + ' and sent them an email with activation instructions.',
                                                self.selenium_wrapper.find_by_css_selector( 'p.flash' ).text )
        # WARNING: if the p.flash sent activation message does not appear check that cookies are cleared correctly

        logging.debug( 'DEBUG: listing users, asserting the new user {} is present'.format( new_user_email ) )
        self.selenium_wrapper.get_url( self.base_url + '/admin/users' )
        self.selenium_wrapper.assert_is_equal( self.base_url + '/admin/users', self.selenium_wrapper.show_current_url() )
        self.selenium_wrapper.assert_css_selector_is_present( 'span[title="' + new_user_email + '"]' )
        self.selenium_wrapper.assert_link_text_is_present( new_user_name )
        self.users.append( (new_user_email, new_user_name) )



    def test_delete_user( self ):
        # Assumes account and user are created
        if len( self.users ) < 2:
            raise AssertionError( 'ERROR: must have at least 2 users in order to delete a user' )

        self.selenium_wrapper.sign_out( self.base_url )
        self.selenium_wrapper.sign_in( self.base_url, self.admin_email, self.admin_password )

        self.selenium_wrapper.get_url( self.base_url + '/admin/users' )
        self.selenium_wrapper.assert_is_equal( self.base_url + '/admin/users', self.selenium_wrapper.show_current_url() )

        target_user_email = self.users[1][0]
        target_user_name = self.users[1][1]
        logging.debug( 'DEBUG: delete user, first click on and show user profile for {} {}'.format( target_user_name, target_user_email ) )
        self.selenium_wrapper.delete_user( target_user_name )

        flash_text = self.selenium_wrapper.find_by_css_selector( 'p.flash' ).text
        logging.debug( 'DEBUG: found text: {}'.format( flash_text ) )
        self.selenium_wrapper.assert_is_equal( flash_text, "User " + target_user_name + " deleted.", )



    def test_add_emoticon( self ):
        # Assumes account and user are created, signed in as admin
        emoticon_shortcut_text = ''.join( random.choice( string.ascii_lowercase ) for a in range(3) )  # random 3 letters
        current_file_path = os.path.realpath( __file__ )
        current_directory_path = os.path.dirname( current_file_path )
        emoticon_file_path = os.path.join( current_directory_path, self.emoticon_file_name )
        if not os.path.isfile( emoticon_file_path ):
            raise AssertionError( "ERROR {} does not exist".format( emoticon_file_path ) )

        logging.debug( 'DEBUG: navigating to emoticon menu' )
        self.selenium_wrapper.find_by_css_selector( 'a.admin > span' ).click( )
        self.selenium_wrapper.find_by_link_text( 'Emoticons' ).click( )
        css_text = self.selenium_wrapper.find_by_css_selector( 'h3.inner_box_header' ).text
        self.selenium_wrapper.assert_is_equal( 'Add new emoticon' , css_text )

        logging.debug( 'DEBUG: filling in form with {} and {}'.format( emoticon_shortcut_text, emoticon_file_path ) )
        self.selenium_wrapper.add_emoticon( emoticon_shortcut_text, emoticon_file_path )
        logging.debug( 'DEBUG: asserting emoticon is uploaded' )
        flash_text = self.selenium_wrapper.find_by_css_selector( 'p.flash' ).text
        self.selenium_wrapper.assert_is_equal( flash_text, 'Successfully uploaded emoticon' )




if __name__ == '__main__':

    if len( sys.argv ) < 2:
        print "usage: python {} server.com [/directory-with-binary/browserbinary] [9134]".format( sys.argv[0] )
        sys.exit( 1 )


    logging_level = logging.DEBUG
    logging_output_filename = 'selenium-integration-test.log'
    logging_output = os.path.join( os.path.normpath( '/tmp' ) , logging_output_filename )
    logging.basicConfig(
        name = 'seleniumIntegration' ,
        level = logging_level ,
        format = '%(asctime)s %(levelname)s %(message)s',
        filename = logging_output,
        filemode = 'w' )



    fqdn_param = sys.argv[1]                    # server.com

    browser_binary = None                 # Firefox default
    port = None

    if len( sys.argv ) == 3:              # Firefox with specified binary path
        browser_binary = sys.argv[2]
    elif len( sys.argv ) > 3:
        browser_binary = sys.argv[2]
        port = int( sys.argv[3] )

    if port:
        if not SeleniumTest.is_valid_connection( 'localhost', port ):
            logging.error( "ERROR: unable to connect to localhost on port {}".format( port ) )
            sys.exit( 1 )

    selenium_wrapper_param = SeleniumTest( executable_path=browser_binary, port=port )
    integration_tests = IntegrationTests( fqdn_param, selenium_wrapper_param )

    test_case_names = [ 'test_sign_up', 'test_sign_in_admin', 'test_add_user', 'test_delete_user', 'test_add_emoticon' ]
    test_case_results = list()

    for test_name in test_case_names:
        test_error = None
        if hasattr( integration_tests, test_name ):
            method_to_call = getattr( integration_tests, test_name )
            starttime = time.time()

            try:
                method_to_call()
            except AssertionError as error:
                logging.debug( "Assertion ERROR {}".format( error ) )
                test_error = error

            elapsed_time = time.time() - starttime
            result = TestCase( name=test_name, elapsed_sec=elapsed_time )
            if test_error:
                result.add_failure_info( 'ERROR: {}'.format( test_error ) )

        else:
            result = TestCase( name=test_name )
            result.add_failure_info( 'ERROR: test {} not implemented'.format( test_name ) )

        test_case_results.append( result )



    test_suite = list()
    test_suite.append( TestSuite( "Integration Test", test_case_results ) )

    print( TestSuite.to_xml_string( test_suite ) )      # TODO: to file?
    selenium_wrapper_param.quit()

  • « junit xml example
  • urllib2 replace requests namedtuple wrapper httperror »

Published

Oct 17, 2013

Category

python

~633 words

Tags

  • integration 5
  • python 180
  • selenium 5
  • tests 5