149 lines
4.7 KiB
Python
149 lines
4.7 KiB
Python
# coding=utf-8
|
|
from __future__ import print_function
|
|
|
|
import unittest
|
|
import subprocess
|
|
import os
|
|
from telenium.client import TeleniumHttpClient
|
|
from time import time, sleep
|
|
from uuid import uuid4
|
|
|
|
|
|
class TeleniumTestCase(unittest.TestCase):
|
|
"""Telenium unittest TestCase, that can be run with any runner like pytest.
|
|
"""
|
|
|
|
#: Telenium url to connect to
|
|
telenium_url = "http://localhost:9901/jsonrpc"
|
|
|
|
#: Timeout of the process to start, in seconds
|
|
process_start_timeout = 5
|
|
|
|
#: Environment variables that can be passed to the process
|
|
cmd_env = {}
|
|
|
|
#: Entrypoint of the process
|
|
cmd_entrypoint = ["main.py"]
|
|
|
|
#: Command to start the process (cmd_entrypoint is appended to this)
|
|
cmd_process = ["python", "-m", "telenium.execute"]
|
|
|
|
_telenium_init = False
|
|
|
|
@classmethod
|
|
def start_process(cls):
|
|
host = os.environ.get("TELENIUM_HOST", "localhost")
|
|
if "TELENIUM_HOST" in os.environ:
|
|
url = "http://{}:{}/jsonrpc".format(
|
|
os.environ.get("TELENIUM_HOST", "localhost"),
|
|
int(os.environ.get("TELENIUM_PORT", "9901")))
|
|
else:
|
|
url = cls.telenium_url
|
|
|
|
cls.telenium_token = str(uuid4())
|
|
cls.cli = TeleniumHttpClient(url=url, timeout=5)
|
|
|
|
# prior test, close any possible previous telenium application
|
|
# to ensure this one might be executed correctly.
|
|
try:
|
|
cls.cli.app_quit()
|
|
sleep(2)
|
|
except:
|
|
pass
|
|
|
|
# prepare the environment of the application to start
|
|
env = os.environ.copy()
|
|
env["TELENIUM_TOKEN"] = cls.telenium_token
|
|
for key, value in cls.cmd_env.items():
|
|
env[key] = str(value)
|
|
cmd = cls.cmd_process + cls.cmd_entrypoint
|
|
|
|
# start the application
|
|
if os.environ.get("TELENIUM_TARGET", None) == "android":
|
|
cls.start_android_process(env=env)
|
|
else:
|
|
cls.start_desktop_process(cmd=cmd, env=env)
|
|
|
|
# wait for telenium server to be online
|
|
start = time()
|
|
while True:
|
|
try:
|
|
cls.cli.ping()
|
|
break
|
|
except Exception:
|
|
if time() - start > cls.process_start_timeout:
|
|
raise Exception("timeout")
|
|
sleep(1)
|
|
|
|
# ensure the telenium we are connected are the same as the one we
|
|
# launched here
|
|
if cls.cli.get_token() != cls.telenium_token:
|
|
raise Exception("Connected to another telenium server")
|
|
|
|
@classmethod
|
|
def start_desktop_process(cls, cmd, env):
|
|
cwd = os.path.dirname(cls.cmd_entrypoint[0])
|
|
cls.process = subprocess.Popen(cmd, env=env, cwd=cwd)
|
|
|
|
@classmethod
|
|
def start_android_process(cls, env):
|
|
import subprocess
|
|
import json
|
|
package = os.environ.get("TELENIUM_ANDROID_PACKAGE", None)
|
|
entry = os.environ.get("TELENIUM_ANDROID_ENTRY",
|
|
"org.kivy.android.PythonActivity")
|
|
telenium_env = cls.cmd_env.copy()
|
|
telenium_env["TELENIUM_TOKEN"] = env["TELENIUM_TOKEN"]
|
|
cmd = [
|
|
"adb", "shell", "am", "start", "-n",
|
|
"{}/{}".format(package, entry), "-a", entry
|
|
]
|
|
|
|
filename = "/tmp/telenium_env.json"
|
|
with open(filename, "w") as fd:
|
|
fd.write(json.dumps(telenium_env))
|
|
cmd_env = ["adb", "push", filename, "/sdcard/telenium_env.json"]
|
|
print("Execute: {}".format(cmd_env))
|
|
subprocess.Popen(cmd_env).communicate()
|
|
print("Execute: {}".format(cmd))
|
|
cls.process = subprocess.Popen(cmd)
|
|
print(cls.process.communicate())
|
|
|
|
@classmethod
|
|
def stop_process(cls):
|
|
cls.cli.app_quit()
|
|
cls.process.wait()
|
|
|
|
@classmethod
|
|
def setUpClass(cls):
|
|
TeleniumTestCase._telenium_init = False
|
|
cls.start_process()
|
|
super(TeleniumTestCase, cls).setUpClass()
|
|
|
|
@classmethod
|
|
def tearDownClass(cls):
|
|
TeleniumTestCase._telenium_init = False
|
|
cls.stop_process()
|
|
super(TeleniumTestCase, cls).tearDownClass()
|
|
|
|
def setUp(self):
|
|
if not TeleniumTestCase._telenium_init:
|
|
if hasattr(self, "init"):
|
|
self.init()
|
|
TeleniumTestCase._telenium_init = True
|
|
|
|
def assertExists(self, selector, timeout=-1):
|
|
self.assertTrue(self.cli.wait(selector, timeout=timeout))
|
|
|
|
def assertNotExists(self, selector, timeout=-1):
|
|
start = time()
|
|
while True:
|
|
matches = self.cli.select(selector)
|
|
if not matches:
|
|
return True
|
|
if timeout == -1:
|
|
raise AssertionError("selector matched elements")
|
|
if timeout > 0 and time() - start > timeout:
|
|
raise Exception("Timeout")
|
|
sleep(0.1)
|