| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135 |
- from py.xml import html
- import pytest
- import subprocess
- import xmlrpc
- import time
- stderr = list()
- stdout = list()
- apperrs = list()
- def pytest_html_results_summary(prefix, summary, postfix):
- prefix.extend([html.h3("stderr")])
- prefix.extend([html.pre("".join([line for line in stderr]))])
- prefix.extend([html.h3("stdout")])
- prefix.extend([html.pre("".join([line for line in stdout]))])
- prefix.extend([html.h3("App errors")])
- prefix.extend([html.pre("".join([line for line in apperrs]))])
- @pytest.fixture
- def process_alive(app, process, process_communicate):
- def func():
- try:
- global apperrs
- # We need to call something on the rpc server
- # the process might still be running but frozen or only almost dead
- apperrs += app.getErrors()
- except Exception as e:
- # Process probably died
- pass
- finally:
- process_communicate()
- exit_code = process.poll()
- if exit_code is not None:
- print(f"Process exited with {exit_code}")
- return exit_code is None
- yield func
- @pytest.fixture
- def process_communicate(process, report_summary):
- def func():
- try:
- output_b, errors_b = process.communicate(timeout=0.1)
- output = output_b.decode("utf-8")
- errors = errors_b.decode("utf-8")
- print(errors)
- print(output)
- report_summary[0].append(output)
- report_summary[1].append(errors)
- except subprocess.TimeoutExpired:
- pass
- yield func
- @pytest.fixture
- def report_summary():
- yield stdout, stderr
- @pytest.fixture
- def process():
- filenames = [
- "./output/bin/qfield",
- "./output/bin/Release/qfield.exe",
- "./output/bin/Debug/qfield.exe",
- "./output/bin/qfield.app/qfield.exe",
- "./output/bin/qfield.app/Contents/MacOS/qfield",
- ]
- for filename in filenames:
- try:
- process = subprocess.Popen(
- filename, stdout=subprocess.PIPE, stderr=subprocess.PIPE
- )
- yield process
- break
- except FileNotFoundError:
- pass
- else:
- assert False, f"No qfield executable found in {filenames}"
- @pytest.fixture
- def app(process, process_communicate):
- """
- Starts a qfield process and connects an xmlrpc client to it.
- Returns the xmlrpc client that can send commands to the running process.
- Will wait up to 30 seconds for the process to start and return as soon
- as either the process is started and QML initialized, the process exits
- or the timeout occurs.
- Also makes sure it cleans up properly after running the app.
- """
- app = xmlrpc.client.ServerProxy("http://localhost:9000")
- app.process = process
- start = time.time()
- while True:
- try:
- exit_code = process.poll()
- if exit_code is not None:
- process_communicate(process)
- assert exit_code is None
- app.existsAndVisible("mainWindow")
- yield app
- break
- except (ConnectionRefusedError, OSError) as e:
- if time.time() - start > 30:
- process_communicate(process)
- assert False # Could not start app after 30 seconds
- print(str(e))
- time.sleep(0.2)
- except Exception as e:
- process_communicate(process)
- assert False # Unexcpected exception while starting up app
- try:
- app.quit()
- app.quit()
- except Exception:
- print("Exception while trying to exit app. The process probably died.")
- process_communicate()
- raise
- timeout = 5
- try:
- process.wait(timeout)
- except subprocess.TimeoutExpired:
- print(f"Process did not quit after {timeout} second. Killing it.")
- process.kill()
- process_communicate()
|