Pesquisar este blog

terça-feira, 22 de setembro de 2015

I will show how to create test automation with ddt and python, with code clean and adaptable in Real Project: Part 3



Appeared an unexpected pre-requirement of our client, our client asked that the tests they are run on multiple browsers, Firefox, Chrome, Internet Explorer by default, of dynamic form and simple. For this lets go now create another class, class with the browsers name, with function to set browser specific chosen and return the browser instantiated.


Create directory classes and create browsers.py:
Our class for example:

__author__ = 'Reinaldo Mateus Rossetti Junior'
from selenium import webdriver
from selenium.webdriver.common.desired_capabilities import DesiredCapabilities

class browsers(object):

    def setBrowser(self,browser):

        if browser == "FIREFOX":
            #Running Standalone Selenium Server for use with RemoteDrivers, port 4441
            WEB_DRIVER = webdriver.Remote(command_executor='http://127.0.0.1:4441/wd/hub',
                   desired_capabilities=DesiredCapabilities.FIREFOX)
            return WEB_DRIVER

        elif browser == "CHROME":
            WEB_DRIVER = webdriver.Remote(command_executor='http://127.0.0.1:4441/wd/hub',
                   desired_capabilities=DesiredCapabilities.CHROME)
            return WEB_DRIVER

        elif browser == "IE":
            WEB_DRIVER = webdriver.Remote(command_executor='http://127.0.0.1:4441/wd/hub',
                   desired_capabilities=DesiredCapabilities.INTERNETEXPLORER)
            return WEB_DRIVER

Now let's go change login_password_ok.csv, include new variables, test_number and browsers:

test_number,login, password, user_type, browsers
001,alex,test@2015,tester,IE
002,luis,luis123,senior tester,IE
003,admin,admin,admin,IE
004,daniel,daniel123,guest,IE
005, jaque,jaque@2015,leader,IE
006,luis,luis123,senior tester,FIREFOX
007,admin,admin,admin,FIREFOX
008,daniel,daniel123,guest,FIREFOX
009,alex,test@2015,tester,FIREFOX
010,jaque,jaque@2015,leader,FIREFOX
011,luis,luis123,senior tester,CHROME
012,admin,admin,admin,CHROME
013,daniel,daniel123,guest,CHROME
014,alex,test@2015,tester,CHROME
015,jaque,jaque@2015,leader,CHROME


Need import new classe, as follows:

from classes.browsers_test import *

Let's go now instantiate the class, as follows:

def setUp(self):

    self.test_browser = browsers()


In our test in login_test.py, need change a little, on function change to receive new variables, as follows:

    def test_login_password_ok(self,test_number,tl_login,tl_password,user_type,browser_type):

For last, now set browser function and pass the browser variable and return instantiates the same.

self.driver = self.test_browser.setBrowser(browser_type)

Too let's go create a list with results of tests.
Test Ok:
list_result.append([test_number,"Passed"])
Test Fail:
list_result.append([test_number,"Failed"])


Now new code with changes:

"""
Author: Reinaldo Mateus R J, Test version: 0.1
Fist Step - Imports modules, in Python code in one module gains access to the code in another module by
    the process of importing.
Second Step - create function get_data in csv file.
Third Step - create class and function specific for test.
"""

import csv, unittest, time, os
from ddt import ddt, data, unpack
from selenium import webdriver
from selenium.webdriver.common.keys import Keys
from selenium.webdriver.support.ui import WebDriverWait
from variables_test import *
from classes.browsers_test import *
global list_result
list_result = []

def get_data(file_name):
    # create an empty list to store rows
    rows = []
    # open the CSV file
    print file_name
    data_file = open(file_name, "rb")
    # create a CSV Reader from CSV file
    reader = csv.reader(data_file)
    # skip the headers
    next(reader, None)
    # add rows from reader to list
    for row in reader:
         rows.append(row)
    return rows

# DDT consists of a class decorator @ddt (for your TestCase subclass)
@ddt
class LoginTestClass(unittest.TestCase,object):

    def setUp(self):

        self.test_browser = browsers()
        # url base of website
        self.base_url = BASE_URL

    # Read the users in rows, and Passing variables tl_login,tl_password,user_type to function test_run.
    @data(*get_data(PATH_TEST_OK))
    # will automatically unpack tuples and lists into multiple arguments, and dictionaries into multiple
    # keyword arguments.
    @unpack
    def test_login_password_ok(self,test_number,tl_login,tl_password,user_type,browser_type):

        self.driver = self.test_browser.setBrowser(browser_type)
        wait = WebDriverWait(self.driver, 90)
        # Try three times if fail.
        for i in range(3):
            try:
                self.driver.get(self.base_url+ LOGIN_PAGE)
                elem = wait.until(lambda driver: driver.find_element_by_name("tl_login"))
                # Send user name in tl_login field
                elem.send_keys(tl_login)
                # Next we are sending keys, this is similar to entering keys using your keyboard.
                elem.send_keys(Keys.RETURN)
                elem = self.driver.find_element_by_name("tl_password")
                # Send password in tl_password field
                elem.send_keys(tl_password)
                # This is similar to entering keys using your keyboard.
                elem.send_keys(Keys.RETURN)
                time.sleep(DELAY_FAST)
                # timeout five seconds
                time.sleep(DELAY_FAST)
                self.driver.get(self.base_url+ MAIN_MENU)
                print "\nTest: ", test_number, tl_login, tl_password, user_type, browser_type
                time.sleep(DELAY_FAST)
                confirm = wait.until(lambda driver: driver.find_element_by_xpath\
                    ("/html/body/div[2]/span[contains(text(),'"+user_type+"')]" ))
                print  confirm.text
                elem_test = str(confirm.text)
                time.sleep(DELAY_FAST)
                # split text in two words in the string.
                elem_test = elem_test.split(" ", 1)
                time.sleep(DELAY_FAST)
                print "Tag value: " + str(elem_test)
                # compare second word with user_type
                if elem_test[1] == "["+user_type+"]":
                    if (self.driver.find_element_by_xpath(XPATH_TOP_TEXT_MAIN_PAGE)):
                        # Test - compare text expected with XPATH_TOP_TEXT_MAIN_PAGE in browser.
                        self.assertTrue((self.driver.find_element_by_xpath(XPATH_TOP_TEXT_MAIN_PAGE).text\
                                         == TOP_TEXT_MAIN_PAGE))
                        print "Test User " +user_type+ " Passed with success! Test Number: ", test_number
                        self.driver.get(self.base_url+ INDEX_MENU)
                        time.sleep(DELAY_HIGH)
                        screenshot = self.driver.get_screenshot_as_file(SCREEN_SAVE + tl_login + "_" + tl_password + "" + user_type +'.png')
                        print "Screenshot saved to: %s" % screenshot
                        list_result.append([test_number,"Passed"])
                        return True
                    else:
                        # Inform if not found the field expected.
                        time.sleep(DELAY_HIGH)
                        # Test - compare text expected with XPATH_TOP_TEXT_MAIN_PAGE in browser.
                        self.assertTrue((self.driver.find_element_by_xpath(XPATH_TOP_TEXT_MAIN_PAGE).text\
                                         == TOP_TEXT_MAIN_PAGE))
                        print "Element Xpath not found: ", tl_login, tl_password, user_type , browser_type

            except:
                pass
                print "Failed! Test Number: ",test_number, tl_login, tl_password, user_type, browser_type
                print "Failed attempts: ", i
                if (i >= 2):
                    list_result.append([test_number,"Failed"])
                time.sleep(DELAY_HIGH)
            # Logout this web application
        self.driver.get(self.base_url+ LOGOUT_PAGE)


    def tearDown(self):

        # function which returns a new sorted list
        list_result.sort()
        print "\nTest Number / Result   "
        for i in xrange(0,len(list_result)):
                print "----------------------------------"
                print list_result[i][0],list_result[i][1]
        self.driver.close()
        # will end the whole session.
        #self.driver.quit()

To execution new test, need selenium-server-standalone-2.47.1.jar
Page to download: http://www.seleniumhq.org/download/
I created .bat file to run selenium-server in windows, follow the tip:
Create new file .txt in desktop and add commands below, rename the file to server selenium.bat

cd\
cd C:\selenium_server\
java -jar selenium-server-standalone-2.47.1.jar -port 4441
pause




Tests Result:
Test Number / Result  
----------------------------------
001 Passed
----------------------------------
002 Passed
----------------------------------
003 Passed
----------------------------------
004 Passed
----------------------------------
005 Passed
----------------------------------
006 Passed
----------------------------------
007 Passed
----------------------------------
008 Passed
----------------------------------
009 Passed
----------------------------------
010 Passed
----------------------------------
011 Passed
----------------------------------
012 Passed
----------------------------------
013 Passed
----------------------------------
014 Passed
----------------------------------
015 Passed


The code is simple is efficient, could use the jenkins for this, but it's good to get out a bit outside the box to good results.

Now let's go the good practices, Refactoring the code.

create new class in classes directory with name:

common_functions.py

Put here all common functions:

 __author__ = 'Reinaldo M. R. Junior'
import csv, unittest, time, os

class functions(object):

    def get_data(self,file_name):
        # create an empty list to store rows
        rows = []
        # open the CSV file
        print file_name
        data_file = open(file_name, "rb")
        # create a CSV Reader from CSV file
        reader = csv.reader(data_file)
        # skip the headers
        next(reader, None)
        # add rows from reader to list
        for row in reader:
             rows.append(row)
        return rows


Create class login in classes:
login.py

Perform Login is used by many classes, and the need to separate, to be used by other classes.

"""
Author: Reinaldo Mateus R J, Test version: 0.1
Fist Step - Imports modules, in Python code in one module gains access to the code in another module by
    the process of importing.
Second Step - create function get_data in csv file.
Third Step - create class and function specific for test.
"""

import time
from selenium.webdriver.common.keys import Keys
from selenium.webdriver.support.ui import WebDriverWait
from variables_test import *


class loginTest(object):

    def test_login_password_ok(self,tl_login,tl_password,user_type,driver):

        #self.test_browser = browsers()
        # url base of website
        self.base_url = BASE_URL
        self.driver = driver
        wait = WebDriverWait(self.driver, 90)

        try:
            self.driver.get(self.base_url+ LOGIN_PAGE)
            elem = wait.until(lambda driver: driver.find_element_by_name("tl_login"))
            # Send user name in tl_login field
            elem.send_keys(tl_login)
            # Next we are sending keys, this is similar to entering keys using your keyboard.
            elem.send_keys(Keys.RETURN)
            elem = self.driver.find_element_by_name("tl_password")
            # Send password in tl_password field
            elem.send_keys(tl_password)
            # This is similar to entering keys using your keyboard.
            elem.send_keys(Keys.RETURN)
            time.sleep(DELAY_FAST)
            # timeout five seconds
            time.sleep(DELAY_FAST)
            self.driver.get(self.base_url+ MAIN_MENU)
            print "\nTest: ", tl_login, tl_password, user_type
            time.sleep(DELAY_FAST)
            confirm = wait.until(lambda driver: driver.find_element_by_xpath\
                ("/html/body/div[2]/span[contains(text(),'"+user_type+"')]" ))
            print  confirm.text
            elem_test = str(confirm.text)
            time.sleep(DELAY_FAST)
            # split text in two words in the string.
            elem_test = elem_test.split(" ", 1)
            time.sleep(DELAY_FAST)
            print "Tag value: " + str(elem_test)
            # compare second word with user_type
            if elem_test[1] == "["+user_type+"]":
                    time.sleep(DELAY_FAST)
                    return elem_test[1]
            else:
                return False

        except (RuntimeError, TypeError, NameError):
            print "Failed! Test Number: ",tl_login, tl_password, user_type
            time.sleep(DELAY_HIGH)
            pass


In variables_test.py create:
list_result = []

Now login_test.py, as follows:

"""
Author: Reinaldo Mateus R J, Test version: 0.1
Fist Step - Imports modules, in Python code in one module gains access to the code in another module by
    the process of importing.
Second Step - create function get_data in csv file.
Third Step - create class and function specific for test.
"""
import unittest, time
from ddt import ddt, data, unpack
from selenium import webdriver
from selenium.webdriver.support.ui import WebDriverWait
from variables_test import *
from classes.browsers_test import *
from classes.common_functions import *
from classes.login import *
commom = functions()
login = loginTest()

# DDT consists of a class decorator @ddt (for your TestCase subclass)
@ddt
class LoginTestClass(unittest.TestCase,object):

    def setUp(self):

        self.test_browser = browsers()
        # url base of website
        self.base_url = BASE_URL
        self.driver = ''

    # Read the users in rows, and Passing variables tl_login,tl_password,user_type to function test_run.
    @data(*commom.get_data(PATH_TEST_OK))
    # will automatically unpack tuples and lists into multiple arguments, and dictionaries into multiple
    # keyword arguments.
    @unpack
    def test_login_password_ok(self,test_number,tl_login,tl_password,user_type,browser_type):

        self.driver = self.test_browser.setBrowser(browser_type)
        wait = WebDriverWait(self.driver, 90)
        # Try three times if fail.
        for i in range(3):
            try:
                elem_test = login.test_login_password_ok(tl_login,tl_password,user_type,self.driver)
                if elem_test == "["+user_type+"]":
                    if (self.driver.find_element_by_xpath(XPATH_TOP_TEXT_MAIN_PAGE)):
                        # Test - compare text expected with XPATH_TOP_TEXT_MAIN_PAGE in browser.
                        self.assertTrue((self.driver.find_element_by_xpath(XPATH_TOP_TEXT_MAIN_PAGE).text\
                                         == TOP_TEXT_MAIN_PAGE))
                        print "Test User " +user_type+ " Passed with success! Test Number: ", test_number
                        self.driver.get(self.base_url+ INDEX_MENU)
                        time.sleep(DELAY_HIGH)
                        screenshot = self.driver.get_screenshot_as_file(SCREEN_SAVE + tl_login + "_" + tl_password + "" + user_type +'.png')
                        print "Screenshot saved to: %s" % screenshot
                        list_result.append([test_number,"Passed"])
                        return True
                    else:
                        # Inform if not found the field expected.
                        time.sleep(DELAY_HIGH)
                        # Test - compare text expected with XPATH_TOP_TEXT_MAIN_PAGE in browser.
                        self.assertTrue((self.driver.find_element_by_xpath(XPATH_TOP_TEXT_MAIN_PAGE).text\
                                         == TOP_TEXT_MAIN_PAGE))
                        print "Element Xpath not found: ", tl_login, tl_password, user_type , browser_type

            except:
                pass
                print "Failed! Test Number: ",test_number, tl_login, tl_password, user_type, browser_type
                print "Failed attempts: ", i
                if (i >= 2):
                    list_result.append([test_number,"Failed"])
                time.sleep(DELAY_HIGH)
            # Logout this web application
        self.driver.get(self.base_url+ LOGOUT_PAGE)


    def tearDown(self):

        # function which returns a new sorted list
        list_result.sort()
        print "\nTest Number / Result   "
        for i in xrange(0,len(list_result)):
                print "----------------------------------"
                print list_result[i][0],list_result[i][1]
        self.driver.close()
        # will end the whole session.
        self.driver.quit()


Now is the half the size it was, and still going be used for functions other classes, refactoring the code is good practice.


Another good practice is commit this code in version control system, below our code committed in bitbucket:

git clone https://reiload@bitbucket.org/reiload/selenium-webdriver-ddt-and-python-with-real-project.git 


In the next Topic about Design Patterns in Selenium.

Read:
http://www.seleniumhq.org/docs/04_webdriver_advanced.jsp
http://www.seleniumhq.org/docs/03_webdriver.jsp#webdriver-and-the-selenium-server



segunda-feira, 21 de setembro de 2015

I will show how to create test automation with ddt and python, with code clean and adaptable in Real Project: Part 2


We will expand our project to other operating systems, Linux and windows for example, our project will be multi-platform, now let's go get the way of our directory and add to our links.

import platform,sys

# GET FULL PATH DIRETORY
f = sys.path[0]
# GET DIRECTORY OF PROJECT
project = f.split("sanity_test", 1)
PROJECT_PATH = project[0]

LOGIN_PAGE = "/login.php?note=expired"
BASE_URL = "http://localhost//testlink-1.9.13"
MAIN_MENU = "/lib/general/navBar.php?tproject_id=0&tplan_id=0&updateMainPage=1"
INDEX_MENU = "//index.php?caller=login"
LOGOUT_PAGE = "/logout.php"
LOGIN_PASS_WIN = PROJECT_PATH + "data\\login_password_ok.csv"
LOGIN_PASS_LIN = PROJECT_PATH + "data/login_password_ok.csv"
LOGIN_FAIL_WIN = PROJECT_PATH + "data\\loginOrPass_failed.csv"
LOGIN_FAIL_LIN = PROJECT_PATH + "data/loginOrPass_failed.csv"
TOP_TEXT_MAIN_PAGE = "TestLink 1.9.13 (Stormbringer)"
XPATH_TOP_TEXT_MAIN_PAGE = "/html/body/div[2]/span[3]"
DELAY_FAST = 3
DELAY_HIGH = 7
SCREEN_SAVE= PROJECT_PATH + "sanity_test\\screenshots\\"

# GET PATH OF ACCORDING WITH OPERATING SYSTEM
platform = platform.uname()[0]
if platform == "Windows":
    PATH_TEST_OK = LOGIN_PASS_WIN
    PATH_TEST_FAIL = LOGIN_FAIL_WIN
elif platform == "Linux":
    PATH_TEST_OK = LOGIN_PASS_LIN
    PATH_TEST_FAIL = LOGIN_FAIL_LIN



Now our main test modified, with screen slot now, need create subdirectoy screenshots in sanity_test.


"""
Author: Reinaldo Mateus R J, Test version: 0.1
Fist Step - Imports modules, in Python code in one module gains access to the code in another module by
    the process of importing.
Second Step - create function get_data in csv file.
Third Step - create class and function specific for test.
"""

import csv, unittest, time, os
from ddt import ddt, data, unpack
from selenium import webdriver
from selenium.webdriver.common.keys import Keys
from selenium.webdriver.support.ui import WebDriverWait
from variables_test import *

def get_data(file_name):
    # create an empty list to store rows
    rows = []
    # open the CSV file
    print file_name
    data_file = open(file_name, "rb")
    # create a CSV Reader from CSV file
    reader = csv.reader(data_file)
    # skip the headers
    next(reader, None)
    # add rows from reader to list
    for row in reader:
         rows.append(row)
    return rows

# DDT consists of a class decorator @ddt (for your TestCase subclass)
@ddt
class LoginTestClass(unittest.TestCase):

    def setUp(self):
        # create a new Firefox session
        self.driver = webdriver.Firefox()
        self.driver.implicitly_wait(10)
        self.driver.maximize_window()
        # url base of website
        self.base_url = BASE_URL

    # Read the users in rows, and Passing variables tl_login,tl_password,user_type to function test_run.
    @data(*get_data(PATH_TEST_OK))
    # will automatically unpack tuples and lists into multiple arguments, and dictionaries into multiple
    # keyword arguments.
    @unpack
    def test_login_password_ok(self,tl_login,tl_password,user_type):

        wait = WebDriverWait(self.driver, 90)
        # Try three times if fail.
        for i in range(3):
            try:
                self.driver.get(self.base_url+ LOGIN_PAGE)
                elem = wait.until(lambda driver: driver.find_element_by_name("tl_login"))
                # Send user name in tl_login field
                elem.send_keys(tl_login)
                # Next we are sending keys, this is similar to entering keys using your keyboard.
                elem.send_keys(Keys.RETURN)
                elem = self.driver.find_element_by_name("tl_password")
                # Send password in tl_password field
                elem.send_keys(tl_password)
                # This is similar to entering keys using your keyboard.
                elem.send_keys(Keys.RETURN)
                time.sleep(DELAY_FAST)
                # timeout five seconds
                time.sleep(DELAY_FAST)
                self.driver.get(self.base_url+ MAIN_MENU)
                print "Test: ", tl_login, tl_password, user_type
                time.sleep(DELAY_FAST)
                confirm = wait.until(lambda driver: driver.find_element_by_xpath\
                    ("/html/body/div[2]/span[contains(text(),'"+user_type+"')]" ))
                print  confirm.text
                elem_test = str(confirm.text)
                time.sleep(DELAY_FAST)
                # split text in two words in the string.
                elem_test = elem_test.split(" ", 1)
                time.sleep(DELAY_FAST)
                print "Tag value: " + str(elem_test)
                # compare second word with user_type
                if elem_test[1] == "["+user_type+"]":
                    if (self.driver.find_element_by_xpath(XPATH_TOP_TEXT_MAIN_PAGE)):
                        # Test - compare text expected with XPATH_TOP_TEXT_MAIN_PAGE in browser.
                        self.assertTrue((self.driver.find_element_by_xpath(XPATH_TOP_TEXT_MAIN_PAGE).text\
                                         == TOP_TEXT_MAIN_PAGE))
                        print "Test User " +user_type+ " Passed with success!", tl_login, tl_password, user_type
                        self.driver.get(self.base_url+ INDEX_MENU)
                        time.sleep(DELAY_HIGH)
                        screenshot = self.driver.get_screenshot_as_file(SCREEN_SAVE + tl_login + "_" + tl_password + "" + user_type +'.png')
                        print "Screenshot saved to: %s" % screenshot
                        return True
                    else:
                        # Inform if not found the field expected.
                        time.sleep(DELAY_HIGH)
                        # Test - compare text expected with XPATH_TOP_TEXT_MAIN_PAGE in browser.
                        self.assertTrue((self.driver.find_element_by_xpath(XPATH_TOP_TEXT_MAIN_PAGE).text\
                                         == TOP_TEXT_MAIN_PAGE))
                        print "Element Xpath not found: ", tl_login, tl_password, user_type

            except:
                pass
                print "Failed!", tl_login, tl_password, user_type
                print "Failed attempts: ", i
                time.sleep(DELAY_HIGH)
            # Logout this web application
            self.driver.get(self.base_url+ LOGOUT_PAGE)


    def tearDown(self):
            # will end the whole session.
            self.driver.quit()


Now our simple code without need another classes, adaptable to multiple platforms!

Let's go now complicate our project, our client asked that the tests they are run on multiple browsers, Firefox, Chrome, Internet Explorer by default.

http://www.vidadetestador.com/2015/09/i-will-show-how-to-create-test_22.html
 

terça-feira, 15 de setembro de 2015

I will show how to create test automation with ddt and python, with code clean and adaptable in Real Project:

By using the data-driven testing approach, we can use a single test to verify different
sets of test cases or test data by driving the test with input and expected values from
an external data source instead of using the hardcoded values every time a test is run.


The ddt library provides the ability to parameterize the test cases written using the
unittest library in Python. We can provide a set of data using ddt to a test case for
data-driven tests.
The ddt library provides a set of class and method decorators that we can use to
create data-driven tests.


 Unmesh Gundecha - A practical guide on automated web testing with Selenium using Python.

 I will show how to create test automation with ddt and python, with code clean and adaptable in Real Project:

 1. Step - Install ddt pack:
We can download and install ddt using the following command line in shell or cmd windows:
pip install ddt

  
Home Page: https://github.com/txels/ddt

 2. Step - Reading values from CSV:
We will use the previous test case and move the data that we supplied to
the @data decorator into a separate CSV file called login_password_ok.csv instead of
keeping it in the script. This data will be stored in a tabular format as shown
in the following screenshot:



3. Install the TestLink in localhost:

Follow the video below:
https://www.youtube.com/watch?v=BaOxsJOpk30

4. Step - Create the users in TestLink :

Follow the video below:


5. Step - Creating the code:

5.1- Now let's go create two files in python:
- login_test.py
- variables_url_test.py - Will contain data that can change at any time.

5.1.1 Create file variables_url_test.py and insert data below:

LOGIN_PAGE = "/login.php?note=expired"
BASE_URL = "http://localhost//testlink-1.9.13"
MAIN_MENU = "/lib/general/navBar.php?tproject_id=0&tplan_id=0&updateMainPage=1"
LOGOUT_PAGE = "/logout.php"
LOGIN_PASS= "C:\\xxx\\xxx\\xxx\\xxx\\data\\login_password_ok.csv"
TOP_TEXT_MAIN_PAGE = "TestLink 1.9.13 (Stormbringer)"
XPATH_TOP_TEXT_MAIN_PAGE = "/html/body/div[2]/span[3]"
DELAY_FAST = 3


5.1.1 Create file login_test.py and insert data below:


"""
Author: Reinaldo Mateus R J, Test version: 0.1
Fist Step - Imports modules, in Python code in one module gains access to the code in another module by
    the process of importing.
Second Step - create function get_data in csv file.
Third Step - create class and function specific for test.
"""

import csv, unittest, time
from ddt import ddt, data, unpack
from selenium import webdriver
from selenium.webdriver.common.keys import Keys
from selenium.webdriver.support.ui import WebDriverWait
from variables_test import *


def get_data(file_name):
    # create an empty list to store rows
    rows = []
    # open the CSV file
    print file_name
    data_file = open(file_name, "rb")
    # create a CSV Reader from CSV file
    reader = csv.reader(data_file)
    # skip the headers
    next(reader, None)
    # add rows from reader to list
    for row in reader:
         rows.append(row)
    return rows

# DDT consists of a class decorator @ddt (for your TestCase subclass)
@ddt
class LoginTestClass(unittest.TestCase):

    def setUp(self):
        # create a new Firefox session
        self.driver = webdriver.Firefox()
        self.driver.implicitly_wait(10)
        self.driver.maximize_window()
        # url base of website
        self.base_url = BASE_URL

    # Read the users in rows, and Passing variables tl_login,tl_password,user_type to function test_run.
    @data(*get_data(LOGIN_PASS))
    # will automatically unpack tuples and lists into multiple arguments, and dictionaries into multiple
    # keyword arguments.
    @unpack
    def test_run(self,tl_login,tl_password,user_type):

        wait = WebDriverWait(self.driver, 90)
        # Try three times if fail.
        for i in range(3):
            try:
                self.driver.get(self.base_url+ LOGIN_PAGE)
                elem = wait.until(lambda driver: driver.find_element_by_name("tl_login"))
                # Send user name in tl_login field
                elem.send_keys(tl_login)
                # Next we are sending keys, this is similar to entering keys using your keyboard.
                elem.send_keys(Keys.RETURN)
                elem = self.driver.find_element_by_name("tl_password")
                # Send password in tl_password field
                elem.send_keys(tl_password)
                # This is similar to entering keys using your keyboard.
                elem.send_keys(Keys.RETURN)
                time.sleep(DELAY_FAST)
                # timeout five seconds
                time.sleep(DELAY_FAST)
                self.driver.get(self.base_url+ MAIN_MENU)
                print "Test: ", tl_login, tl_password, user_type
                time.sleep(DELAY_FAST)
                confirm = wait.until(lambda driver: driver.find_element_by_xpath\
                    ("/html/body/div[2]/span[contains(text(),'"+user_type+"')]" ))
                print  confirm.text
                elem_test = str(confirm.text)
                time.sleep(DELAY_FAST)
                # split text in two words in the string.
                elem_test = elem_test.split(" ", 1)
                time.sleep(DELAY_FAST)
                print "Tag value: " + str(elem_test)
                # compare second word with user_type
                if elem_test[1] == "["+user_type+"]":
                    if (self.driver.find_element_by_xpath(XPATH_TOP_TEXT_MAIN_PAGE)):
                        # Test - compare text expected with XPATH_TOP_TEXT_MAIN_PAGE in browser.
                        self.assertTrue((self.driver.find_element_by_xpath(XPATH_TOP_TEXT_MAIN_PAGE).text\
                                         == TOP_TEXT_MAIN_PAGE))
                        print "Test User " +user_type+ " Passed with success!", tl_login, tl_password, user_type
                        break
                    else:
                        # Inform if not found the field expected.
                        time.sleep(10)
                        # Test - compare text expected with XPATH_TOP_TEXT_MAIN_PAGE in browser.
                        self.assertTrue((self.driver.find_element_by_xpath(XPATH_TOP_TEXT_MAIN_PAGE).text\
                                         == TOP_TEXT_MAIN_PAGE))
                        print "Element Xpath not found: ", tl_login, tl_password, user_type

            except:
                pass
                print "Failed!", tl_login, tl_password, user_type
                print "Failed attempts: ", i
                time.sleep(7)
            # Logout this web application
            self.driver.get(self.base_url+ LOGOUT_PAGE)

    def tearDown(self):
            # close the browser window
            self.driver.quit()


From basic mode we finished our tests, but not the testing activity is carried out to find the defects in the code & improve the quality of software application. Testing of application can be carried out in two different ways, Positive testing and Negative testing. Keep in mind that both positive and negative testing is equally important for effective testing which help to improve quality of software.


Negative Test scenarios:
Login and Password wrong, should not accept.
Login ok and Password wrong, should not accept.
Login wrong and Password ok, should not accept.
Password textbox should not exceeds more than 20 characters
Password textbox should not accept special characters.


Now we will expand our project to other operating systems in part two:
http://www.vidadetestador.com/2015/09/i-will-show-how-to-create-test_21.html


quinta-feira, 13 de agosto de 2015

Como aumentar o import da suite de teste no TestLink


Quando tentamos importar uma suite de testes para outro Projeto, muita das vezes a suite é maior que o permitido por padrão. Aconteceu comigo a pouco tempo, devemos fazer as alterações abaixo, para suportar 10 Mbytes e não termos mais problemas.

No config.inc.php, vamos alterar as seguintes linhas:

-> Tamanho Máximo que podemos Importar
/** Maximum uploadfile size to importing stuff in TL */

$tlCfg->import_file_max_size_bytes = ‘409600’;

-> Numero Máximo de Linhas que podem ser importadas
// the maximum allowed file size for each repository entry, default 1MB.

$tlCfg->import_max_row = ‘10000’; // in chars




-> O Máximo tamanho permitido para cada repositório.
// the maximum allowed file size for each repository entry

$tlCfg->repository_max_filesize = 1; //MB 


Para os valores 10485760, 100000, 10  :

$tlCfg->import_file_max_size_bytes = ‘10485760’;
$tlCfg->import_max_row = ‘100000’; // in chars
$tlCfg->repository_max_filesize = 10; //MB

No php.ini, vamos alterar as seguintes linhas, para os valores abaixo:

max_execution_time = 1800
upload_max_filesize = 50M
post_max_size = 50M
memory_limit = 128M

No linux o caminho:
sudo gedit /etc/php5/apache2/php.ini



Por precaução vamos para o serviço do apache e iniciar novamente:

Em Linux:
/etc/init.d/apache2 stop
/etc/init.d/apache2 restart

** Use o sudo caso der problema de permissão.

terça-feira, 11 de agosto de 2015

Python vs Java na Automação de Testes


   A muito tempo quero fazer uma comparação entre Python e Java para automação de testes. Vejo que a maioria dos treinamento são em Java para automação de testes. No entanto as outras linguagens são esquecidas como Python principalmente, é pouco falado e disseminado entre as empresas, sendo que Python é muito mais rápido a linha de aprendizado que Java.  No entanto o aprendizado em Java leva muito mais tempo e treinamento. 
   Vamos falar do ponto mais importante que é produtividade.  Fiz um pequeno teste usando a própria ferramenta do Selenium IDE pra medir a produtividade, medindo pela quantidade de linhas de código gerada pela própria ferramenta, exportando para as devidas linguagem.

Passo 01: 
Foram gravado os seguintes passos:
1. Abrir o google;
2. Pesquisar pelo assunto "Amazon";
3. Selecionar o Link e em seguida pesquisar pelo assunto "Python";
4. Selecionar o livro "Use a Cabeça! Python";
5. Clicar no botão "adicione ao carrinho".

Passo 02:
Agora vamos exportar o script gerado, seguindo as opções "Arquivo - Exportar Teste como..."
Vamos exportar com as opções abaixo:
 Python 2 / unittest / WebDriver
Java / Unit 4 / WebDriver

Passo 03:
Agora vamos abrir com o notepad++ e avaliar a quantidade de linhas de código:
Python - 55 Linhas - 2133 Caracteres
Java - 77 Linhas - 2233 Caracteres

Analisando o código gerado a ferramenta criou o método main do python pra fazer a chamada da classe e no java ela não fez isso, fazendo o mesmo a quantidade de linhas no java ia ser bem maior.

if __name__ == "__main__":
    unittest.main()


Quantidade de imports, vemos que no Python temos 7 linhas de import e no java temos 8 linhas.

from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.common.keys import Keys
from selenium.webdriver.support.ui import Select
from selenium.common.exceptions import NoSuchElementException
from selenium.common.exceptions import NoAlertPresentException
import unittest, time, re


Otimizado um pouco o nosso código ficaria com 3 linhas e funcionaria de boa, não sendo necessário as outras:

from selenium import webdriver
from selenium.common.exceptions import NoSuchElementException, NoAlertPresentException
import unittest, time, re

No Python não precisamos colocar ; no final das variáveis, pelo que contei no código em java tivemos 38 ponto e vírgula, isso é desvantagem, sem falar dos parentheses. Uma característica marcada no Python é a identação do código é obrigatório que o código esteja alinhado de forma correta, isso facilita muito a manutenção do código, se torna fácil de entender a lógica e os loops, no caso do java a ferramenta fez a organização do código, mas não é assim que os desenvolvedores fazem, dificilmente você vai encontrar um código bem arrumado.

No código abaixo não sei porque a ferramenta criou driver = self.driver, podemos muito bem usar direto self.driver em todas as linhas, não precisando criar driver = self.driver, removemos com isso mais uma linha ficando com 50 linhas / 1970 Caracteres do nosso código, contra 77 linhas / 2233 Caracteres do java, aqui vemos 263 Caracteres que em python podemos ser mais produtivo que em Java. 
   É claro que é meio difícil medir a produtividade, simplesmente porque cada pessoa tem a sua velocidade e existe a IDEs como Eclipse e Pycharm que tem o code completion, Java é uma linguagem muito poderosa, mas na automação de testes não utilizamos nem 30% dela, no entanto Java é muito mais verboso e tem um tempo maior de aprendizado que Python. No meu caso, eu codifico scripts de testes em Python, posso dizer que é muito prático e rápido de codificar, no Python você pode usar o extend em mais de uma classe, no Java você não consegue isso, mas existe outras formas pra contornar em java, mas não de forma prática como no Python.
 


Código em Python:
# -*- coding: utf-8 -*-from selenium import webdriver
from selenium.common.exceptions import NoSuchElementException, NoAlertPresentException
import unittest, time, re

class SeliniumPython(unittest.TestCase):
    def setUp(self):
        self.driver = webdriver.Firefox()
        self.driver.implicitly_wait(30)
        self.base_url = "https://www.google.com.br/"        self.verificationErrors = []
        self.accept_next_alert = True        def test_selinium_python(self):
        self.driver.get(self.base_url + "/search?q=amazon&ie=utf-8&oe=utf-8&gws_rd=cr&ei=2JXKVZSXDMKXgwSSnLWYAw")
        self.driver.find_element_by_link_text("Amazon.com.br: compre livros, eBooks, e-readers Kindle e ...").click()
        self.driver.find_element_by_id("twotabsearchtextbox").click()
        self.driver.find_element_by_id("twotabsearchtextbox").clear()
        self.driver.find_element_by_id("twotabsearchtextbox").send_keys("python")
        self.driver.find_element_by_css_selector("input.nav-input").click()
        self.driver.find_element_by_xpath("//li[@id='result_3']/div/div/div/div[2]/div/a/h2").click()
        self.driver.find_element_by_id("bb_atc_button").click()
    
    def is_element_present(self, how, what):
        try: self.driver.find_element(by=how, value=what)
        except NoSuchElementException, e: return False 
        return True    
    def is_alert_present(self):
        try: self.driver.switch_to_alert()
        except NoAlertPresentException, e: return False
        return True
    def close_alert_and_get_its_text(self):
        try:
            alert = self.driver.switch_to_alert()
            alert_text = alert.text
            if self.accept_next_alert:
                alert.accept()
            else:
                alert.dismiss()
            return alert_text
        finally: self.accept_next_alert = True
    def tearDown(self):
        self.driver.quit()
        self.assertEqual([], self.verificationErrors)

if __name__ == "__main__":
    unittest.main()

Código em Java:
package com.example.tests;
import java.util.regex.Pattern;
import java.util.concurrent.TimeUnit;
import org.junit.*;
import static org.junit.Assert.*;
import static org.hamcrest.CoreMatchers.*;
import org.openqa.selenium.*;
import org.openqa.selenium.firefox.FirefoxDriver;
import org.openqa.selenium.support.ui.Select;

public class SeleniumJava {
  private WebDriver driver;
  private String baseUrl;
  private boolean acceptNextAlert = true;
  private StringBuffer verificationErrors = new StringBuffer();

  @Before
  public void setUp() throws Exception {
    driver = new FirefoxDriver();
    baseUrl = "https://www.google.com.br/";
    driver.manage().timeouts().implicitlyWait(30, TimeUnit.SECONDS);
  }

  @Test
  public void testSeleniumJava() throws Exception {
    driver.get(baseUrl + "/search?q=amazon&ie=utf-8&oe=utf-8&gws_rd=cr&ei=2JXKVZSXDMKXgwSSnLWYAw");
    driver.findElement(By.linkText("Amazon.com.br: compre livros, eBooks, e-readers Kindle e ...")).click();
    driver.findElement(By.id("twotabsearchtextbox")).click();
    driver.findElement(By.id("twotabsearchtextbox")).clear();
    driver.findElement(By.id("twotabsearchtextbox")).sendKeys("python");
    driver.findElement(By.cssSelector("input.nav-input")).click();
    driver.findElement(By.xpath("//li[@id='result_3']/div/div/div/div[2]/div/a/h2")).click();
    driver.findElement(By.id("bb_atc_button")).click();
  }

  @After
  public void tearDown() throws Exception {
    driver.quit();
    String verificationErrorString = verificationErrors.toString();
    if (!"".equals(verificationErrorString)) {
      fail(verificationErrorString);
    }
  }

  private boolean isElementPresent(By by) {
    try {
      driver.findElement(by);
      return true;
    } catch (NoSuchElementException e) {
      return false;
    }
  }

  private boolean isAlertPresent() {
    try {
      driver.switchTo().alert();
      return true;
      catch (NoAlertPresentException e)
      return false;
    
  }

  private String closeAlertAndGetItsText() {
    try {
      Alert alert = driver.switchTo().alert();
      String alertText = alert.getText();
      if (acceptNextAlert) {
        alert.accept();
      } else {
        alert.dismiss();
      }
      return alertText;
    } finally {
      acceptNextAlert = true;
    }
  }
}