Desktop automation PoC
Signed-off-by: yevh-berdnyk <ie.berdnyk@gmail.com>
This commit is contained in:
parent
d823bfd71c
commit
55d72b534a
|
@ -0,0 +1,2 @@
|
|||
[pytest]
|
||||
addopts = -s -v --junitxml=result.xml --tb=line
|
|
@ -0,0 +1,16 @@
|
|||
atomicwrites==1.2.1
|
||||
attrs==18.2.0
|
||||
certifi==2018.8.24
|
||||
chardet==3.0.4
|
||||
funcsigs==1.0.2
|
||||
idna==2.7
|
||||
jip==0.9.13
|
||||
more-itertools==4.3.0
|
||||
pathlib2==2.3.2
|
||||
pluggy==0.7.1
|
||||
py==1.6.0
|
||||
pytest==2.7.2
|
||||
requests==2.19.1
|
||||
scandir==1.9.0
|
||||
six==1.11.0
|
||||
urllib3==1.23
|
|
@ -0,0 +1,52 @@
|
|||
import org.sikuli.script.SikulixForJython
|
||||
import pytest
|
||||
from sikuli import *
|
||||
from subprocess import check_output
|
||||
|
||||
|
||||
def mac_os_setup():
|
||||
check_output(['hdiutil', 'attach', 'nightly.dmg'])
|
||||
check_output(['cp', '-rf', '/Volumes/Status/Status.app', '/Applications/'])
|
||||
check_output(['hdiutil', 'detach', '/Volumes/Status/'])
|
||||
import time
|
||||
time.sleep(10)
|
||||
openApp('Status.app')
|
||||
|
||||
|
||||
def mac_os_teardown():
|
||||
closeApp('Status.app')
|
||||
for dir in '/Applications/Status.app', '/Library/Application\ Support/StatusIm', \
|
||||
'/Users/yberdnyk/Library/Caches/StatusIm':
|
||||
check_output(['rm', '-rf', dir])
|
||||
|
||||
|
||||
def linux_setup():
|
||||
check_output(['chmod', '+x', './nightly.AppImage'])
|
||||
check_output(['./nightly.AppImage', '--appimage-extract'])
|
||||
check_output(['chmod', '+x', '/src/squashfs-root/AppRun'])
|
||||
openApp('/src/squashfs-root/AppRun')
|
||||
|
||||
|
||||
def linux_teardown():
|
||||
pass
|
||||
# check_output(['killall', 'ubuntu-server'])
|
||||
# check_output(['rm', '-rf', '~/.local/share/StatusIm/'])
|
||||
# check_output(['rm', '-rf', '~/.cache/StatusIm/'])
|
||||
|
||||
|
||||
class BaseTestCase:
|
||||
Settings.ActionLogs = 0
|
||||
Settings.OcrTextSearch = True
|
||||
Settings.OcrTextRead = True
|
||||
|
||||
def setup_method(self, method):
|
||||
if pytest.config.getoption('os') == 'linux':
|
||||
linux_setup()
|
||||
else:
|
||||
mac_os_setup()
|
||||
|
||||
def teardown_method(self, method):
|
||||
if pytest.config.getoption('os') == 'linux':
|
||||
linux_teardown()
|
||||
else:
|
||||
mac_os_teardown()
|
|
@ -0,0 +1,56 @@
|
|||
import org.sikuli.script.SikulixForJython
|
||||
from sikuli import *
|
||||
import pytest
|
||||
import requests
|
||||
import re
|
||||
from urllib import urlretrieve
|
||||
from subprocess import check_output
|
||||
|
||||
from tests.report import save_test_result, TEST_REPORT_DIR
|
||||
|
||||
|
||||
def pytest_addoption(parser):
|
||||
parser.addoption('--os',
|
||||
action='store',
|
||||
default='linux')
|
||||
parser.addoption("--nightly",
|
||||
action="store",
|
||||
default=True)
|
||||
parser.addoption('--dmg',
|
||||
action='store',
|
||||
default=None,
|
||||
help='Url or local path to dmg')
|
||||
|
||||
|
||||
def pytest_configure(config):
|
||||
if config.getoption('nightly'):
|
||||
raw_data = requests.request('GET', 'https://status-im.github.io/nightly/').text
|
||||
if config.getoption('os') == 'linux':
|
||||
app_url = re.findall('href="(.*AppImage)', raw_data)[0]
|
||||
urlretrieve(app_url, 'nightly.AppImage')
|
||||
else:
|
||||
dmg_url = re.findall('href="(.*dmg)', raw_data)[0]
|
||||
urlretrieve(dmg_url, 'nightly.dmg')
|
||||
|
||||
|
||||
@pytest.mark.hookwrapper
|
||||
def pytest_runtest_makereport(item, call):
|
||||
import logging
|
||||
# logging.basicConfig(filename='%s/%s.log' % (TEST_REPORT_DIR, item.name), filemode='w', level=logging.INFO)
|
||||
outcome = yield
|
||||
report = outcome.get_result()
|
||||
if report.when == 'call':
|
||||
pass
|
||||
# save_test_result(item, report)
|
||||
|
||||
|
||||
def after_all():
|
||||
if pytest.config.getoption('os') == 'linux':
|
||||
check_output(['rm', '-rf', 'nightly.AppImage'])
|
||||
else:
|
||||
check_output(['rm', '-rf', 'nightly.dmg'])
|
||||
|
||||
|
||||
@pytest.fixture(scope="session", autouse=True)
|
||||
def before_all(request):
|
||||
request.addfinalizer(finalizer=after_all)
|
|
@ -0,0 +1,33 @@
|
|||
import json
|
||||
import os
|
||||
from subprocess import check_output
|
||||
|
||||
TEST_REPORT_DIR = "%s/../report" % os.path.dirname(os.path.abspath(__file__))
|
||||
|
||||
|
||||
def get_test_report_file_path(test_name):
|
||||
file_name = "%s.json" % test_name
|
||||
if not os.path.exists(TEST_REPORT_DIR):
|
||||
os.makedirs(TEST_REPORT_DIR)
|
||||
return os.path.join(TEST_REPORT_DIR, file_name)
|
||||
|
||||
|
||||
def get_testrail_case_id(obj):
|
||||
if 'testrail_id' in obj.keywords._markers:
|
||||
return obj.keywords._markers['testrail_id'].args[0]
|
||||
|
||||
|
||||
def save_test_result(test, report):
|
||||
test_name = test.name
|
||||
file_path = get_test_report_file_path(test_name)
|
||||
if report.failed:
|
||||
check_output(['screencapture', '%s/%s.png' % (TEST_REPORT_DIR, test_name)])
|
||||
with open('%s/%s.log' % (TEST_REPORT_DIR, test_name), 'r') as log:
|
||||
steps = [i for i in log]
|
||||
test_dict = {
|
||||
'testrail_case_id': get_testrail_case_id(test),
|
||||
'name': test_name,
|
||||
'steps': steps,
|
||||
'error': str(report.longrepr.reprcrash.message),
|
||||
'screenshot': test_name + '.png'}
|
||||
json.dump(test_dict, open(file_path, 'w'))
|
|
@ -0,0 +1,16 @@
|
|||
from tests.base_test_case import BaseTestCase
|
||||
from views.sign_in_view import SignInView
|
||||
|
||||
|
||||
class TestCreateAccount(BaseTestCase):
|
||||
|
||||
def test_create_account(self):
|
||||
sign_in = SignInView()
|
||||
sign_in.create_account_button.click()
|
||||
sign_in.password_input.input_value('123456')
|
||||
sign_in.next_button.click()
|
||||
sign_in.confirm_password_input.input_value('123456')
|
||||
sign_in.next_button.click()
|
||||
sign_in.username_input.input_value('test')
|
||||
sign_in.next_button.click()
|
||||
sign_in.home_button.find_element()
|
|
@ -0,0 +1,27 @@
|
|||
import logging
|
||||
import org.sikuli.script.SikulixForJython
|
||||
import pytest
|
||||
from sikuli import *
|
||||
|
||||
|
||||
class BaseElement(object):
|
||||
def __init__(self, screenshot):
|
||||
self.screenshot = screenshot
|
||||
|
||||
def find_element(self):
|
||||
try:
|
||||
wait(self.screenshot, 10)
|
||||
except FindFailed:
|
||||
pytest.fail('%s was not found' % self.__class__.__name__)
|
||||
|
||||
def click(self):
|
||||
logging.info('Click %s' % self.__class__.__name__)
|
||||
self.find_element()
|
||||
click(self.screenshot)
|
||||
|
||||
|
||||
class InputField(BaseElement):
|
||||
|
||||
def input_value(self, value):
|
||||
self.click()
|
||||
type(value)
|
|
@ -0,0 +1,17 @@
|
|||
import os
|
||||
|
||||
from views.base_element import BaseElement
|
||||
|
||||
IMAGES_PATH = os.path.join(os.path.dirname(__file__), 'images/base_view')
|
||||
|
||||
|
||||
class HomeButton(BaseElement):
|
||||
def __init__(self):
|
||||
super(HomeButton, self).__init__(IMAGES_PATH + '/home_button.png')
|
||||
|
||||
|
||||
class BaseView(object):
|
||||
|
||||
def __init__(self):
|
||||
super(BaseView, self).__init__()
|
||||
self.home_button = HomeButton()
|
Binary file not shown.
After Width: | Height: | Size: 6.9 KiB |
Binary file not shown.
After Width: | Height: | Size: 15 KiB |
Binary file not shown.
After Width: | Height: | Size: 13 KiB |
Binary file not shown.
After Width: | Height: | Size: 6.7 KiB |
Binary file not shown.
After Width: | Height: | Size: 14 KiB |
Binary file not shown.
After Width: | Height: | Size: 12 KiB |
|
@ -0,0 +1,41 @@
|
|||
import os
|
||||
|
||||
from views.base_element import BaseElement, InputField
|
||||
from views.base_view import BaseView
|
||||
|
||||
IMAGES_PATH = os.path.join(os.path.dirname(__file__), 'images/sign_in_view')
|
||||
|
||||
|
||||
class CreateAccountButton(BaseElement):
|
||||
def __init__(self):
|
||||
super(CreateAccountButton, self).__init__(IMAGES_PATH + '/create_account.png')
|
||||
|
||||
|
||||
class PasswordInput(InputField):
|
||||
def __init__(self):
|
||||
super(PasswordInput, self).__init__(IMAGES_PATH + '/password_input.png')
|
||||
|
||||
|
||||
class ConfirmPasswordInput(InputField):
|
||||
def __init__(self):
|
||||
super(ConfirmPasswordInput, self).__init__(IMAGES_PATH + '/confirm_password_input.png')
|
||||
|
||||
|
||||
class UserNameInput(InputField):
|
||||
def __init__(self):
|
||||
super(UserNameInput, self).__init__(IMAGES_PATH + '/username_input.png')
|
||||
|
||||
|
||||
class NextButton(InputField):
|
||||
def __init__(self):
|
||||
super(NextButton, self).__init__(IMAGES_PATH + '/next_button.png')
|
||||
|
||||
|
||||
class SignInView(BaseView):
|
||||
def __init__(self):
|
||||
super(SignInView, self).__init__()
|
||||
self.create_account_button = CreateAccountButton()
|
||||
self.password_input = PasswordInput()
|
||||
self.confirm_password_input = ConfirmPasswordInput()
|
||||
self.username_input = UserNameInput()
|
||||
self.next_button = NextButton()
|
Loading…
Reference in New Issue