Rewrited Web UI tests. Moved all tests to behave framework.

This commit is contained in:
Timur Nurlygayanov
2013-04-17 10:36:36 +04:00
parent d6aa49b412
commit eb4814a18b
22 changed files with 971 additions and 0 deletions

0
selenium/__init__.py Normal file
View File

View File

@@ -0,0 +1,18 @@
Feature: Active Directories
Scenario: Create AD service with 1 instance
Given browser with new environment "test01" details page
When I create AD service "ad.local" with 1 instances
Then page should contain link "ad.local"
Scenario: Create AD service with 3 instances
Given browser with new environment "test02" details page
When I create AD service "AD.net" with 3 instances
Then page should contain link "AD.net"
Scenario: Create a few AD services
Given browser with new environment "test03" details page
When I create AD service "AD.net" with 1 instances
And I create AD service "test_ad.service" with 2 instances
Then page should contain link "AD.net"
And page should contain link "test_ad.service"

View File

@@ -0,0 +1,55 @@
Feature: Deploy environments
Scenario: Deploy environment with AD service
Given browser with new environment "env1_for_deploy" details page
When I create AD service "ad.test" with 1 instances
And I deploy environment "env1_for_deploy"
Then environment "env1_for_deploy" has status "Deploy In Progress"
And environment "env1_for_deploy" has progress bar
Scenario: Check status of AD service
Given browser with environment "env1_for_deploy" details page
Then service "ad.test" has status "Deploy In Progress"
And service "ad.test" has progress bar
Scenario: Deploy environment with IIS service
Given browser with new environment "env2_for_deploy" details page
When I create IIS service "iis_service" without domain
And I deploy environment "env2_for_deploy"
Then environment "env2_for_deploy" has status "Deploy In Progress"
And environment "env2_for_deploy" has progress bar
Scenario: Check status of IIS service
Given browser with environment "env2_for_deploy" details page
Then service "iis_service" has status "Deploy In Progress"
And service "iis_service" has progress bar
Scenario: Deploy environment with AD and IIS services
Given browser with new environment "env3_for_deploy" details page
When I create AD service "ad.test" with 2 instances
And I create IIS service "iis_service" in domain ad.test
And I create IIS service "iis_service2" in domain ad.test
And I deploy environment "env3_for_deploy"
Then environment "env3_for_deploy" has status "Deploy In Progress"
And environment "env3_for_deploy" has progress bar
Scenario: Check environment status before deploy
Given browser with new environment "env4_for_deploy" details page
When I create AD service "ad-test" with 1 instances
And I create IIS service "iis_service" in domain ad-test
Then environment "env4_for_deploy" has status "Ready To Deploy"
And environment "env4_for_deploy" has no progress bar
Scenario: Check status of services before deploy
Given browser with environment "env4_for_deploy" details page
Then service "ad-test" has status "Ready To Deploy"
And service "ad-test" has no progress bar
And service "iis_service" has status "Ready To Deploy"
And service "iis_service" has no progress bar

38
selenium/environment.py Normal file
View File

@@ -0,0 +1,38 @@
import logging
from datetime import datetime
from steps.login_page import LoginPage
from selenium import webdriver
LOG = logging.getLogger(__name__)
def before_all(context):
context.screenshots = True
context.driver = webdriver.Firefox()
context.page = LoginPage(context.driver)
context.page.login()
def after_all(context):
context.driver.close()
def before_tag(context, tag):
if tag == 'time':
context.start = datetime.now()
def after_tag(context, tag):
if tag == 'time':
result = datetime.now() - context.start
LOG.info("Test Case: " + str(result))
def before_scenario(context, scenario):
context.test_case = scenario
def before_step(context, step):
screenshot_name = "%s_%s.png".format(context.test_case, step)
if context.screenshots:
context.driver.save_screenshot(screenshot_name)

View File

@@ -0,0 +1,24 @@
Feature: Environments
Scenario: Create environment
Given browser with Environments page
When I create environment "env1"
Then page should contain link "env1"
Scenario: Delete environment
Given browser with Environments page
When I create environment "env2"
And I delete environment "env2"
Then page should not contain link "env2"
Scenario: Delete environments
Given browser with Environments page
When I create environment "env3"
And I create environment "env4"
And I create environment "env5"
And I delete environment "env3"
And I delete environment "env5"
Then page should not contain link "env3"
And page should not contain link "env5"
And page should contain link "env4"

21
selenium/iis.feature Normal file
View File

@@ -0,0 +1,21 @@
Feature: IIS service
Scenario: Create IIS service without domain
Given browser with new environment "iis_test01" details page
When I create IIS service "iis" without domain
Then page should contain link "iis"
Scenario: Create IIS service with domain
Given browser with new environment "iis_test02" details page
When I create AD service "ad.service" with 1 instances
And I create IIS service "iis.server" in domain ad.service
Then page should contain link "iis.server"
Scenario: Create a few IIS services
Given browser with new environment "iis_test03" details page
When I create AD service "AD-NET" with 1 instances
And I create AD service "ad.service" with 2 instances
And I create IIS service "iis.server1" in domain AD-NET
And I create IIS service "iis.server2" in domain ad.service
Then page should contain link "iis.server1"
And page should contain link "iis.server2"

View File

@@ -0,0 +1,22 @@
<objects>
<object>
<type>Button</type>
<name>More</name>
<parameter>.//*[@id='windc__row__%s']/td[4]/div/a[2]</parameter>
</object>
<object>
<type>Button</type>
<name>Delete</name>
<parameter>windc__row_%s__action_delete</parameter>
</object>
<object>
<type>Button</type>
<name>Deploy</name>
<parameter>windc__row_%s__action_deploy</parameter>
</object>
<object>
<type>TableCell</type>
<name>Status</name>
<parameter>.//*[@id='windc__row__%s']/td[3]</parameter>
</object>
</objects>

View File

@@ -0,0 +1,37 @@
<objects>
<object>
<type>Button</type>
<name>More</name>
<parameter>.//*[@id='services__row__%s']/td[5]/div/a[2]</parameter>
</object>
<object>
<type>Button</type>
<name>Delete</name>
<parameter>services__row_%s__action_delete</parameter>
</object>
<object>
<type>Button</type>
<name>CreateService</name>
<parameter>services__action_CreateService</parameter>
</object>
<object>
<type>TableCell</type>
<name>Name</name>
<parameter>.//*[@id='services_details___service']/div/dl/dd[1]</parameter>
</object>
<object>
<type>TableCell</type>
<name>Domain</name>
<parameter>.//*[@id='services_details___service']/div/dl/dd[3]</parameter>
</object>
<object>
<type>Link</type>
<name>Service</name>
<parameter>.//*[@id='services_details']/li[1]/a</parameter>
</object>
<object>
<type>TableCell</type>
<name>Status</name>
<parameter>.//*[@id='services__row__%s']/td[4]</parameter>
</object>
</objects>

View File

@@ -0,0 +1,7 @@
<objects>
<object>
<type>Button</type>
<name>Create</name>
<parameter>//input[@value='Create']</parameter>
</object>
</objects>

View File

@@ -0,0 +1,16 @@
Feature: services details
Scenario: Check AD service parameters in details
Given browser with new environment "d_test01" details page
When I create AD service "ad" with 1 instances
And I navigate to service "ad" details page
Then service name should be equal to "ad"
Then service domain should be equal to "ad"
Scenario: Check IIS service parameters in details
Given browser with new environment "d_test02" details page
When I create AD service "ad.test" with 1 instances
And I create IIS service "iis_service" in domain ad.test
And I navigate to service "iis_service" details page
Then service name should be equal to "iis_service"
Then service domain should be equal to "ad.test"

View File

BIN
selenium/steps/__init__.pyc Normal file

Binary file not shown.

96
selenium/steps/_steps.py Normal file
View File

@@ -0,0 +1,96 @@
import logging
from login_page import LoginPage
from environments_page import EnvironmentsPage
from services_page import ServicesPage
from selenium import webdriver
from behave import *
logging.basicConfig()
LOG = logging.getLogger(' Tests: ')
@given('browser with Environments page')
def step(browser):
browser.page.Navigate('Project>Environments')
browser.page = EnvironmentsPage(browser.driver)
@given('browser with environment "{environment_name}" details page')
def step(browser, environment_name):
browser.page.Navigate("Project>Environments>%s" % environment_name)
browser.page = ServicesPage(browser.driver)
@given('browser with new environment "{environment_name}" details page')
def step(browser, environment_name):
page = browser.page
page.Navigate("Project>Environments")
page = EnvironmentsPage(browser.driver)
page.create_environment(environment_name)
page.Navigate(environment_name)
browser.page = ServicesPage(browser.driver)
@when('I create environment "{environment_name}"')
def step(browser, environment_name):
browser.page.create_environment(environment_name)
@when('I create AD service "{ad_name}" with {ad_count} instances')
def step(browser, ad_name, ad_count=1):
parameters = {'1-dc_name': ad_name,
'1-dc_count': ad_count,
'1-adm_password': "P@ssw0rd",
'1-recovery_password': "P@ssw0rd2"}
browser.page.create_service("Active Directory", parameters)
@when('I create IIS service "{iis_name}" without domain')
@when('I create IIS service "{iis_name}" in domain {iis_domain}')
def step(browser, iis_name, iis_domain=''):
parameters = {'1-iis_name': iis_name,
'1-adm_password': "P@ssw0rd",
'1-iis_domain': iis_domain}
browser.page.create_service("Internet Information Services", parameters)
@when('I delete environment "{environment_name}"')
def step(browser, environment_name):
browser.page.delete_environment(environment_name)
@when('I navigate to service "{service_name}" details page')
def step(browser, service_name):
page = browser.page
page.Navigate(service_name)
page.Link('Service').Click()
@then('page should contain link "{link_text}"')
def step(browser, link_text):
assert browser.page.Link(link_text).isPresented()
@then('page should not contain link "{link_text}"')
def step(browser, link_text):
assert not browser.page.Link(link_text).isPresented()
@then('{element} "{element_name}" has {parameter}')
def step(browser, element, element_name, parameter):
page = browser.page
status = ""
if element == 'environment':
status = page.get_environment_status(element_name)
elif element == 'service':
status = page.get_service_status(element_name)
progress_bar = '<img src="/static/dashboard/img/loading.gif">'
if 'status' in parameter:
assert parameter[8:-1] in status
elif 'no progress bar' in parameter:
assert not progress_bar in status
elif 'progress bar' in parameter:
assert progress_bar in status

View File

@@ -0,0 +1,56 @@
# Copyright (c) 2013 Mirantis Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
# implied.
# See the License for the specific language governing permissions and
# limitations under the License.
import re
from services_page import ServicesPage
import page
class EnvironmentsPage(page.Page):
name = 'Environments'
def create_environment(self, name):
self.Refresh()
self.Button('Create Environment').Click()
self.EditBox('id_name').Set(name)
self.Button('Create').Click()
def delete_environment(self, name):
self.Refresh()
link = self.Link(name).Address()
environment_id = re.search('tabula/(\S+)', link).group(0)[7:-1]
self.Button('More', environment_id).Click()
self.Button('Delete', environment_id).Click()
# confirm:
self.Button('Delete Environment').Click()
def deploy_environment(self, name):
self.Refresh()
link = self.Link(name).Address()
environment_id = re.search('tabula/(\S+)', link).group(0)[7:-1]
self.Button('More', environment_id).Click()
self.Button('Deploy', environment_id).Click()
def get_environment_status(self, name):
self.Refresh()
link = self.Link(name).Address()
environment_id = re.search('tabula/(\S+)', link).group(0)[7:-1]
return self.TableCell('Status', environment_id).Text()

Binary file not shown.

View File

@@ -0,0 +1,36 @@
# Copyright (c) 2013 Mirantis Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
# implied.
# See the License for the specific language governing permissions and
# limitations under the License.
import ConfigParser
import page
class LoginPage(page.Page):
def login(self):
config = ConfigParser.RawConfigParser()
config.read('conf.ini')
url = config.get('server', 'address')
user = config.get('server', 'user')
password = config.get('server', 'password')
self.Open(url)
self.EditBox('username').Set(user)
self.EditBox('password').Set(password)
xpath = "//button[@type='submit']"
self.Button(xpath).Click()
return self

Binary file not shown.

278
selenium/steps/page.py Normal file
View File

@@ -0,0 +1,278 @@
# Copyright (c) 2013 Mirantis Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
# implied.
# See the License for the specific language governing permissions and
# limitations under the License.
import logging
from selenium.webdriver.support.ui import Select
import xml.etree.ElementTree as ET
logging.basicConfig()
LOG = logging.getLogger(' Page object: ')
"""
Disable selenium logging:
"""
logger = logging.getLogger('selenium.webdriver.remote.remote_connection')
logger.setLevel('ERROR')
class ObjectsLibrary:
file = None
objects = []
def __init__(self, file_name='objects/objects.xml'):
"""
Initialization of the Objects Library.
Read objects descriptions from XML file.
"""
self.file = file_name
tree = ET.parse(self.file)
objects = tree.getroot()
self.objects = []
for element in objects:
object = {}
for parameter in element:
object.update({parameter.tag: parameter.text})
self.objects.append(object)
def get_object(self, name):
"""
Search objects in Objects Library.
"""
for object in self.objects:
if object['name'] == name:
return object['parameter']
return None
class TableCellClass:
table = None
def __init__(self, obj):
if not obj:
LOG.error('TableCell does not found')
self.table = obj
def Text(self):
if self.table:
LOG.critical(self.table.text)
return self.table.text
else:
return ''
class ButtonClass:
button = None
def __init__(self, obj):
if not obj:
LOG.error('Button does not found')
self.button = obj
def Click(self):
if self.button:
self.button.click()
def isPresented(self):
if self.button:
return True
return False
class LinkClass:
link = None
def __init__(self, obj):
if not obj:
LOG.error('Link does not found')
self.link = obj
def Click(self):
if self.link:
self.link.click()
def isPresented(self):
if self.link:
return True
return False
def Address(self):
if self.link:
return self.link.get_attribute('href')
else:
return ''
class EditBoxClass:
def __init__(self, obj):
if not obj:
LOG.error('EditBox does not found')
self.edit = obj
def isPresented(self):
if self.edit:
return True
return False
def Set(self, value):
if self.edit:
try:
self.edit.clear()
self.edit.send_keys(value)
except:
LOG.error('Can not set value for text box.')
def Text(self):
if self.edit:
return self.edit.get_text()
else:
return ''
class DropDownListClass:
select = None
def __init__(self, obj):
if not obj:
LOG.error('DropDownList does not found')
self.select = obj
def isPresented(self):
if self.select is not None:
return True
return False
def Set(self, value):
if self.select:
try:
Select(self.select).select_by_visible_text(value)
except:
LOG.error("Can not select element %s from drop down list."
.format(value))
def Text(self):
if self.select:
return self.select.get_text()
else:
return ''
error_msg = """
Object with parameter: %s
does not found on page.
"""
class Page:
driver = None
timeout = 30
lib = None
name = None
def __init__(self, driver):
driver.set_page_load_timeout(self.timeout)
driver.implicitly_wait(0.1)
self.driver = driver
def _find_element(self, name, parameter=None):
"""
This method allows to find element,
based on descriptions in Object Library,
xpath, id, name or pertial link text.
If parameter != None will be used name % parameter
"""
lib_name = "objects/objects.xml"
if self.name:
lib_name = "objects/%s.xml".format(self.name)
lib = ObjectsLibrary(lib_name)
if lib.get_object(name):
name = lib.get_object(name)
if parameter:
name = name % parameter
obj = None
k = 0
while (obj is None and k < self.timeout):
k += 1
try:
obj = self.driver.find_element_by_name(name)
return obj
except:
pass
try:
obj = self.driver.find_element_by_id(name)
return obj
except:
pass
try:
obj = self.driver.find_element_by_xpath(name)
return obj
except:
pass
try:
obj = self.driver.find_element_by_partial_link_text(name)
return obj
except:
pass
LOG.error(error_msg % name)
return None
def Open(self, url):
self.driver.get(url)
def Refresh(self):
self.driver.refresh()
def TableCell(self, name, parameter=None):
obj = self._find_element(name, parameter)
table = TableCellClass(obj)
return table
def Button(self, name, parameter=None):
obj = self._find_element(name, parameter)
button = ButtonClass(obj)
return button
def Link(self, name, parameter=None):
obj = self._find_element(name, parameter)
link = LinkClass(obj)
return link
def EditBox(self, name, parameter=None):
obj = self._find_element(name, parameter)
edit = EditBoxClass(obj)
return edit
def DropDownList(self, name, parameter=None):
obj = self._find_element(name, parameter)
select = DropDownListClass(obj)
return select
def Navigate(self, path):
"""
This method allows to navigate by
webUI menu button and links to
the specific page
"""
steps = path.split('>')
for step in steps:
self.Button(step).Click()

BIN
selenium/steps/page.pyc Normal file

Binary file not shown.

View File

@@ -0,0 +1,61 @@
# Copyright (c) 2013 Mirantis Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
# implied.
# See the License for the specific language governing permissions and
# limitations under the License.
import page
import re
class ServicesPage(page.Page):
name = 'Services'
def create_service(self, service_type, parameters):
self.Refresh()
self.Button('CreateService').Click()
self.DropDownList('0-service').Set(service_type)
self.Button('wizard_goto_step').Click()
for key in parameters:
try:
self.EditBox(key).Set(parameters[key])
except:
pass
try:
self.DropDownList(key).Set(parameters[key])
except:
pass
self.Button('Create').Click()
def delete_service(self, name):
self.Refresh()
link = self.Link(name).Address()
service_id = re.search('tabula/(\S+)', link).group(0)[7:-1]
self.Button('More', service_id).Click()
self.Button('Delete', service_id).Click()
# confirm:
self.Button('Delete Service').Click()
def get_service_status(self, name):
self.Refresh()
link = self.Link(name).Address()
service_id = re.search('tabula/(\S+)', link).group(0)[7:-8]
return self.TableCell('Status', service_id).Text()

Binary file not shown.

206
selenium/steps/test.py Normal file
View File

@@ -0,0 +1,206 @@
# Copyright (c) 2013 Mirantis Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
# implied.
# See the License for the specific language governing permissions and
# limitations under the License.
import unittest2
import logging
from login_page import LoginPage
from environments_page import EnvironmentsPage
from services_page import ServicesPage
from selenium import webdriver
logging.basicConfig()
LOG = logging.getLogger(' Tests: ')
page = None
def generate_ad(name="test", count=1):
"""
This function generates parameters for
Active Directory service
"""
ad_parameters = {'1-dc_name': name,
'1-dc_count': count,
'1-adm_password': "P@ssw0rd",
'1-recovery_password': "P@ssw0rd2"}
return ['Active Directory', ad_parameters]
def generate_iis(name="test", domain="test"):
"""
This function generates parameters for
Internet Information Services service
"""
iis_parameters = {'1-iis_name': name,
'1-adm_password': "P@ssw0rd",
'1-iis_domain': domain}
return ['Internet Information Services', iis_parameters]
environment_for_deploy = 'environment_for_deploy'
class SanityTests(unittest2.TestCase):
screenshots = 0 # Make screenshots for the end of each test
@classmethod
def setUpClass(self):
"""
Open browser, navigate to the login page,
login and navigate to the Windows Data Centers page
"""
driver = webdriver.Firefox()
page = LoginPage(driver)
page.login()
@classmethod
def tearDownClass(self):
"""
Close browser
"""
page.driver.close()
def setUp(self):
"""
Navigate to the start page
"""
page.Navigate('Project:Environments')
page = EnvironmentsPage(driver)
def tearDown(self):
"""
Make screenshot
"""
self.screenshots += 1
page.driver.save_screenshot("screen_%s.png" % self.screenshots)
def test_001_create_environment(self):
page.create_environment('dc1')
assert page.Link('dc1').isPresented()
def test_002_delete_environment(self):
page.delete_environment('dc1')
assert not page.Link('dc1').isPresented()
def test_003_create_environment_before_deploy(self):
ad_name = "AD.net"
iis_name = "iis_server"
page.create_environment(environment_for_deploy)
def test_004_configure_environment_before_deploy(self):
page.Navigate(environment_for_deploy)
page = ServicesPage(driver)
page.create_service(generate_ad(ad_name, 2))
assert page.Link(ad_name).isPresented()
page.create_service(generate_iis(iis_name, ad_name))
assert page.Link(iis_name).isPresented()
def test_005_deploy_environment(self):
page.deploy_environment(environment_for_deploy)
status = page.get_environment_status(environment_for_deploy)
assert 'Deploy in progress' in status
def test_006_create_environments(self):
for i in range(1, 10):
name = "environment" + str(i)
page.create_environment(name)
assert page.Link(name).isPresented()
def test_007_delete_environments(self):
page.delete_environment('environment1')
page.delete_environment('environment9')
assert not page.Link('environment1').isPresented()
assert not page.Link('environment9').isPresented()
for i in range(2, 9):
name = 'environment' + str(i)
assert page.Link(name).isPresented()
def test_008_create_service_ad(self):
env_name = 'test05'
name = "dc001.local"
page.create_environment(env_name)
page.Navigate(env_name)
page = ServicesPage(driver)
page.create_service(generate_ad(name, 1))
assert page.Link(name).isPresented()
def test_009_create_service_ad_two_instances(self):
env_name = 'test06'
name = "dc002.local"
page.create_environment(env_name)
page.Navigate(env_name)
page = ServicesPage(driver)
page.create_service(generate_ad(name, 2))
assert page.Link(name).isPresented()
def test_010_create_service_ad_with_iis(self):
env_name = 'test07'
ad_name = "dc003.local"
page.create_environment(env_name)
page.Navigate(env_name)
page = ServicesPage(driver)
page.create_service(generate_ad(ad_name, 3))
assert page.Link(ad_name).isPresented()
for i in range(5):
iis_name = 'iis_server' + str(i)
page.create_service(generate_iis(iis_name, ad_name))
assert page.Link(iis_name).isPresented()
def test_011_delete_environment_with_services(self):
name = "test07"
page.delete_environment(name)
assert not page.Link(name).isPresented()
def test_012_service_deploy_in_progress_status(self):
ad_name = "AD.net"
iis_name = "iis_server"
page.Navigate(environment_for_deploy)
page = ServicesPage(driver)
ad_status = page.get_service_status(ad_name)
iis_status = page.get_service_status(iis_name)
assert 'Deploy in progress' in ad_status
assert 'Deploy in progress' in iis_status
def test_013_show_service_details_for_deploy(self):
ad_name = "AD.net"
iis_name = "iis_server"
page.Navigate(environment_for_deploy)
page = ServicesPage(driver)
page.Navigate(iis_name)
page.Link('Service').Click()
name = page.TableCell('Name').Text()
domain = page.TableCell('Domain').Text()
assert name == iis_name
assert domain == ad_name
if __name__ == '__main__':
unittest2.main()