Skip to content

Commit e7ebbea

Browse files
Vladimir.RoschinVladimir.Roschin
Vladimir.Roschin
authored and
Vladimir.Roschin
committed
add test login and add/delete
1 parent a45bfb5 commit e7ebbea

12 files changed

+417
-0
lines changed

conftest.py

+84
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
import pytest
2+
import json
3+
import os.path
4+
import ftputil
5+
from fixture.application import Application
6+
import importlib
7+
8+
fixture = None
9+
target = None
10+
11+
12+
def load_config(file):
13+
global target
14+
if target is None:
15+
config_file = os.path.join(os.path.dirname(os.path.abspath(__file__)), file)
16+
with open(config_file) as f:
17+
target = json.load(f)
18+
return target
19+
20+
21+
@pytest.fixture(scope="session")
22+
def config(request):
23+
return load_config(request.config.getoption("--target"))
24+
25+
26+
@pytest.fixture
27+
def app(request, config):
28+
global fixture
29+
browser = request.config.getoption("--browser")
30+
if fixture is None or not fixture.is_valid():
31+
fixture = Application(browser=browser, base_url=config['web']['baseUrl'])
32+
return fixture
33+
34+
35+
@pytest.fixture(scope="session", autouse=True)
36+
def configure_server(request, config):
37+
install_server_configuration(config['ftp']['host'], config['ftp']['username'], config['ftp']['password'])
38+
39+
def fin():
40+
restore_server_configuration(config['ftp']['host'], config['ftp']['username'], config['ftp']['password'])
41+
42+
request.addfinalizer(fin)
43+
44+
45+
def install_server_configuration(host, username, password):
46+
with ftputil.FTPHost(host, username, password) as remote:
47+
if remote.path.isfile("config_inc.php.bak"):
48+
remote.remove("config_inc.php.bak")
49+
if remote.path.isfile("config_inc.php"):
50+
remote.rename("config_inc.php", "config_inc.php.bak")
51+
remote.upload(os.path.join(os.path.dirname(__file__), "resources/config_inc.php"), "config_inc.php")
52+
53+
54+
def restore_server_configuration(host, username, password):
55+
with ftputil.FTPHost(host, username, password) as remote:
56+
if remote.path.isfile("config_inc.php.bak"):
57+
if remote.path.isfile("config_inc.php"):
58+
remote.remove("config_inc.php")
59+
remote.rename("config_inc.php.bak", "config_inc.php")
60+
61+
62+
@pytest.fixture(scope="session", autouse=True)
63+
def stop(request):
64+
def fin():
65+
fixture.session.ensure_logout()
66+
fixture.destroy()
67+
68+
request.addfinalizer(fin)
69+
return fixture
70+
71+
72+
@pytest.fixture
73+
def check_ui(request):
74+
return request.config.getoption("--check_ui")
75+
76+
77+
def pytest_addoption(parser):
78+
parser.addoption("--browser", action="store", default="firefox")
79+
parser.addoption("--target", action="store", default="target.json")
80+
parser.addoption("--check_ui", action="store_true")
81+
82+
83+
def load_from_module(module):
84+
return importlib.import_module("data.%s" % module).testdata

data/projects.py

+15
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
from model.project import Project
2+
import random
3+
import string
4+
5+
6+
def random_string(prefix, maxlen):
7+
symbols = string.ascii_letters + " " * 10
8+
return prefix + "".join([random.choice(symbols) for i in range(random.randrange(maxlen))])
9+
10+
11+
testdata = [
12+
Project(name=random_string("name", 10), status=random.choice(['development', 'release', 'stable', 'obsolete']),
13+
view_state="public", description=random_string("description", 10))
14+
for i in range(1)
15+
]

fixture/application.py

+36
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
from fixture.project import ProjectHelper
2+
from selenium import webdriver
3+
from fixture.session import SessionHelper
4+
5+
6+
class Application:
7+
8+
def __init__(self, browser, base_url):
9+
if browser == "firefox":
10+
self.wd = webdriver.Firefox()
11+
elif browser == "chrome":
12+
self.wd = webdriver.Chrome()
13+
elif browser == "edge":
14+
self.wd = webdriver.Edge()
15+
elif browser == "ie":
16+
self.wd = webdriver.Ie()
17+
else:
18+
raise ValueError("Unrecognized browser %s" % browser)
19+
self.wd.implicitly_wait(5)
20+
self.session = SessionHelper(self)
21+
self.project = ProjectHelper(self)
22+
self.base_url = base_url
23+
24+
def is_valid(self):
25+
try:
26+
self.wd.current_url
27+
return True
28+
except:
29+
return False
30+
31+
def open_home_page(self):
32+
wd = self.wd
33+
wd.get(self.base_url)
34+
35+
def destroy(self):
36+
self.wd.quit()

fixture/db.py

+76
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
import pymysql.cursors
2+
from model.group import Group
3+
from model.add_new import AddNew
4+
import re
5+
6+
7+
class DbFixture:
8+
9+
def __init__(self, host, name, user, password):
10+
self.host = host
11+
self.name = name
12+
self.user = user
13+
self.password = password
14+
self.connection = pymysql.connect(host=host, database=name, user=user, password=password, autocommit=True)
15+
16+
def get_group_list(self):
17+
list = []
18+
cursor = self.connection.cursor()
19+
try:
20+
cursor.execute("select group_id, group_name, group_header, group_footer from group_list")
21+
for row in cursor:
22+
(id, name, header, footer) = row
23+
list.append(Group(id=str(id), name=name, header=header, footer=footer))
24+
finally:
25+
cursor.close()
26+
return list
27+
28+
def get_contact_list(self):
29+
list = []
30+
cursor = self.connection.cursor()
31+
try:
32+
cursor.execute(
33+
"select id, firstname, lastname, address, home, mobile, work, email, email2, email3, phone2 from addressbook where deprecated='0000-00-00 00:00:00'")
34+
for row in cursor:
35+
(id, firstname, lastname, address, home, mobile, work, email, email2, email3, phone2) = row
36+
current_contact = AddNew(my_id=str(id), my_f_name=firstname, my_l_name=lastname,
37+
my_home_address=address,
38+
my_h_telefon=home, my_mobile=mobile, my_work_telefon=work,
39+
my_secondary_phone=phone2,
40+
my_company_mail=email, my_second_mail=email2, my_third_mail=email3
41+
)
42+
final_contact = AddNew(my_id=str(id), my_f_name=self.removing_spaces(firstname),
43+
my_l_name=self.removing_spaces(lastname),
44+
my_home_address=self.removing_spaces(address)
45+
)
46+
final_contact.all_phones_from_home_page = self.merge_phones_like_on_home_page(current_contact)
47+
final_contact.all_emails_from_home_page = self.merge_emails_like_on_home_page(current_contact)
48+
list.append(final_contact)
49+
50+
finally:
51+
cursor.close()
52+
return list
53+
54+
def destroy(self):
55+
self.connection.close()
56+
57+
def clear(self, s):
58+
return re.sub("[() -]", "", s)
59+
60+
def merge_phones_like_on_home_page(self, contacts):
61+
return "\n".join(filter(lambda x: x != "",
62+
map(lambda x: self.clear(x),
63+
filter(lambda x: x is not None,
64+
[contacts.my_h_telefon, contacts.my_mobile, contacts.my_work_telefon,
65+
contacts.my_secondary_phone]))))
66+
67+
def merge_emails_like_on_home_page(self, contacts):
68+
69+
return "\n".join(filter(lambda x: x != "",
70+
map(lambda x: self.clear(x),
71+
filter(lambda x: x is not None,
72+
[contacts.my_company_mail, contacts.my_second_mail,
73+
contacts.my_third_mail]))))
74+
75+
def removing_spaces(self, s):
76+
return re.sub(" ", " ", s.strip())

fixture/project.py

+86
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
from selenium.webdriver.support.ui import Select
2+
from model.project import Project
3+
4+
5+
class ProjectHelper:
6+
7+
def __init__(self, app):
8+
self.app = app
9+
10+
def open_manage_projects_page(self):
11+
wd = self.app.wd
12+
wd.get("http://localhost/mantisbt-1.2.20/manage_proj_page.php")
13+
14+
def open_add_project_page(self):
15+
wd = self.app.wd
16+
self.open_manage_projects_page()
17+
if not wd.current_url.endswith("/manage_proj_create_page.php"):
18+
wd.find_element_by_xpath("//input[@value='Create New Project']").click()
19+
self.implicitly_wait(3)
20+
21+
def create_project(self, project):
22+
wd = self.app.wd
23+
self.open_add_project_page()
24+
self.fill_project_form(project)
25+
# submit project creation
26+
wd.find_element_by_xpath("//input[@value='Add Project']").click()
27+
self.implicitly_wait(5)
28+
29+
def fill_project_form(self, project):
30+
wd = self.app.wd
31+
self.change_field_value("name", project.name)
32+
self.select_dropdown_value("status", project.status)
33+
self.select_dropdown_value("view_state", project.view_state)
34+
self.change_field_value("description", project.description)
35+
self.implicitly_wait(1)
36+
37+
def change_field_value(self, field_name, text):
38+
wd = self.app.wd
39+
if text is not None:
40+
wd.find_element_by_name(field_name).click()
41+
wd.find_element_by_name(field_name).clear()
42+
wd.find_element_by_name(field_name).send_keys(text)
43+
44+
def select_dropdown_value(self, field_name, text):
45+
wd = self.app.wd
46+
if text is not None:
47+
wd.find_element_by_name(field_name).click()
48+
Select(wd.find_element_by_name(field_name)).select_by_visible_text(text)
49+
# wd.find_element_by_link_text(text).click()
50+
51+
def delete_project_by_id(self, id):
52+
wd = self.app.wd
53+
self.open_manage_projects_page()
54+
self.select_project_by_id(id)
55+
self.implicitly_wait(1)
56+
wd.find_element_by_xpath("//input[@value='Delete Project']").click()
57+
wd.find_element_by_xpath("//input[@value='Delete Project']").click()
58+
self.project_cache = None
59+
self.implicitly_wait(2)
60+
61+
def select_project_by_id(self, id):
62+
wd = self.app.wd
63+
wd.find_element_by_xpath("//a[@href='manage_proj_edit_page.php?project_id=%s']" % id).click()
64+
65+
project_cache = None
66+
67+
def get_project_list(self):
68+
wd = self.app.wd
69+
self.open_manage_projects_page()
70+
self.project_cache = []
71+
all_tables = wd.find_elements_by_xpath("//table[@class='width100']")
72+
table = all_tables[1]
73+
rows = table.find_elements_by_xpath(".//tr[contains(@class, 'row')]")
74+
del rows[0]
75+
for element in rows:
76+
cells = element.find_elements_by_tag_name("td")
77+
name = cells[0].text
78+
description_text = cells[4].text
79+
id_link = wd.find_element_by_link_text(name).get_attribute("href")
80+
id_index = id_link.index('=') + 1
81+
id = id_link[id_index:]
82+
self.project_cache.append(Project(id=id, name=name, description=description_text))
83+
return list(self.project_cache)
84+
85+
def implicitly_wait(self, param):
86+
pass

fixture/session.py

+44
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
class SessionHelper:
2+
3+
def __init__(self, app):
4+
self.app = app
5+
6+
def login(self, username, password):
7+
wd = self.app.wd
8+
self.app.open_home_page()
9+
wd.find_element_by_name("username").click()
10+
wd.find_element_by_name("username").clear()
11+
wd.find_element_by_name("username").send_keys(username)
12+
wd.find_element_by_name("password").click()
13+
wd.find_element_by_name("password").send_keys(password)
14+
wd.find_element_by_xpath("//input[@value='Login']").click()
15+
16+
def logout(self):
17+
wd = self.app.wd
18+
wd.find_element_by_link_text("Logout").click()
19+
20+
def is_logged_in(self):
21+
wd = self.app.wd
22+
return len(wd.find_elements_by_link_text("Logout")) > 0
23+
24+
def is_logged_in_as(self, username):
25+
wd = self.app.wd
26+
return self.get_logged_user() == username
27+
28+
def get_logged_user(self):
29+
wd = self.app.wd
30+
return wd.find_element_by_css_selector("td.login-info-left span").text
31+
32+
def ensure_logout(self):
33+
wd = self.app.wd
34+
if self.is_logged_in():
35+
self.logout()
36+
37+
def ensure_login(self, username, password):
38+
wd = self.app.wd
39+
if self.is_logged_in():
40+
if self.is_logged_in_as(username):
41+
return
42+
else:
43+
self.logout()
44+
self.login(username, password)

model/project.py

+23
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
from sys import maxsize
2+
3+
4+
class Project:
5+
6+
def __init__(self, id=None, name=None, status=None, view_state=None, description=None):
7+
self.id = id
8+
self.name = name
9+
self.status = status
10+
self.view_state = view_state
11+
self.description = description
12+
13+
def __repr__(self):
14+
return "%s;%s;%s;%s;%s" % (self.id, self.name, self.status, self.view_state, self.description)
15+
16+
def __eq__(self, other):
17+
return (self.id == other.id or self.id is None or other.id is None) and self.name == other.name
18+
19+
def id_or_max(self):
20+
if self.id:
21+
return int(self.id)
22+
else:
23+
return maxsize

resourses/config_inc.php

+7
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
<?php
2+
$g_hostname = 'localhost';
3+
$g_db_type = 'mysqli';
4+
$g_database_name = 'bugtracker';
5+
$g_db_username = 'root';
6+
$g_db_password = '';
7+
$g_use_captcha = OFF;

target.json

+14
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
{
2+
"web": {
3+
"baseUrl": "http://localhost/mantisbt-1.2.20/"
4+
},
5+
"webadmin": {
6+
"username": "administrator",
7+
"password": "root"
8+
},
9+
"ftp": {
10+
"host": "localhost",
11+
"username": "mantis",
12+
"password": "mantis"
13+
}
14+
}

0 commit comments

Comments
 (0)