-
Notifications
You must be signed in to change notification settings - Fork 3
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #80 from sunyhydralab/printer-refactor
Printer refactor
- Loading branch information
Showing
109 changed files
with
76,654 additions
and
7,173 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,70 @@ | ||
import os | ||
import sys | ||
import re | ||
import subprocess | ||
import platform | ||
|
||
# Add test root to sys.path if needed | ||
from globals import root_path | ||
if root_path not in sys.path: | ||
sys.path.append(root_path) | ||
serverpath = os.path.join(root_path, "server") | ||
if serverpath not in sys.path: | ||
sys.path.append(serverpath) | ||
testpath = os.path.join(root_path, "Tests") | ||
if testpath not in sys.path: | ||
sys.path.append(testpath) | ||
|
||
from server.Classes.Ports import Ports | ||
|
||
PORTS = [] | ||
# List of available ports for testing | ||
if platform.system() == "Windows": | ||
import winreg | ||
path = "HARDWARE\\DEVICEMAP\\SERIALCOMM" | ||
try: | ||
key = winreg.OpenKey(winreg.HKEY_LOCAL_MACHINE, path) | ||
for i in range(256): | ||
try: | ||
val = winreg.EnumValue(key, i) | ||
if re.match(r"COM\d+|LPT\d+", val[1]): | ||
PORTS.append(val[1]) | ||
except OSError: | ||
break | ||
except FileNotFoundError: | ||
pass | ||
elif platform.system() == "Darwin": | ||
import glob | ||
PORTS = glob.glob("/dev/tty.*") | ||
else: | ||
import glob | ||
PORTS = glob.glob("/dev/tty[A-Za-z]*") | ||
|
||
|
||
|
||
# Function to run pytest for a specific port | ||
testLevel = 10 | ||
verbosity = 2 | ||
runFlags = 0b010 # 0b001: -s, 0b010: -vvv or -p no:terminal, 0b100: debug or info | ||
|
||
def run_tests_for_port(comm_port): | ||
env = os.environ.copy() | ||
env["PORT"] = comm_port | ||
args = ["pytest", testpath, f"--myVerbose={verbosity}", f"--port={comm_port}"] | ||
if runFlags & 0b1: args.append("-s") | ||
args.append("-vv") if runFlags & 0b10 else args.append("-p no:terminal") | ||
env["LEVEL"] = "DEBUG" if runFlags & 0b100 else "INFO" | ||
subprocess.Popen(args, env=env).wait() | ||
|
||
if __name__ == "__main__": | ||
from concurrent.futures import ThreadPoolExecutor, as_completed | ||
if len(PORTS) != 0: | ||
with ThreadPoolExecutor(max_workers=len(PORTS)) as executor: | ||
futures = [executor.submit(run_tests_for_port, port) for port in PORTS if | ||
Ports.getPortByName(port) is not None] | ||
for future in as_completed(futures): | ||
try: | ||
future.result() | ||
except Exception as e: | ||
from globals import current_app | ||
current_app.handle_errors_and_logging(e) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,146 @@ | ||
import os | ||
import re | ||
import pytest | ||
from Classes.Logger import Logger | ||
from parallel_test_runner import testLevel | ||
|
||
def __desc__(): return "App Tests" | ||
|
||
@pytest.mark.dependency() | ||
@pytest.mark.skipif(condition=testLevel < 1, reason="Not doing lvl 1 tests") | ||
def test_db_to_make_sure_it_has_valid_file_path(app): | ||
db_file_no_path = app.config["SQLALCHEMY_DATABASE_URI"].split("/")[-1].split("\\")[-1] | ||
assert db_file_no_path, "database_uri doesn't exist?" | ||
assert db_file_no_path == "hvamc.db", f"database_uri is {db_file_no_path}" | ||
assert os.path.exists(app.config["SQLALCHEMY_DATABASE_URI"].split("sqlite:///")[ | ||
-1]), f"Database file {app.config["SQLALCHEMY_DATABASE_URI"].split("sqlite:///")[-1]} does not exist" | ||
|
||
|
||
@pytest.mark.dependency(depends=["test_db_to_make_sure_it_has_valid_file_path"]) | ||
@pytest.mark.skipif(condition=testLevel < 1, reason="Not doing lvl 1 tests") | ||
def test_base_url_for_http_responses_has_valid_format(app): | ||
assert app.config["base_url"], "base_url doesnt exist?" | ||
assert re.match(r"http://\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}:\d{1,5}$", app.config["base_url"]) or re.match( | ||
r"http://localhost:\d{1,5}$", app.config["base_url"]), f"base_url is {app.config['base_url']}" | ||
|
||
|
||
@pytest.mark.dependency(depends=["test_base_url_for_http_responses_has_valid_format"]) | ||
@pytest.mark.skipif(condition=testLevel < 1, reason="Not doing lvl 1 tests") | ||
def test_environment_for_development(app): | ||
assert app.config["environment"], "environment doesnt exist?" | ||
assert app.config["environment"] == "development", f"environment is {app.config['environment']}" | ||
|
||
|
||
@pytest.mark.dependency(depends=["test_environment_for_development"]) | ||
@pytest.mark.skipif(condition=testLevel < 1, reason="Not doing lvl 1 tests") | ||
def test_logger_is_custom_implementation_and_exists(app): | ||
assert app.logger, "myLogger doesnt exist?" | ||
assert app.logger.name, "name doesnt exist?" | ||
assert str(app.logger.name) == "Logger_App", f"myLogger is {str(app.logger.name)}" | ||
assert isinstance(app.logger, Logger), "myLogger is not an instance of Logger?" | ||
assert app.logger.fileLogger, "fileLogger doesnt exist?" | ||
|
||
|
||
@pytest.mark.dependency(depends=["test_logger_is_custom_implementation_and_exists"]) | ||
@pytest.mark.skipif(condition=testLevel < 1, reason="Not doing lvl 1 tests") | ||
def test_socketio_exists_and_works(app): | ||
assert app.socketio, "socketio doesnt exist?" | ||
assert app.socketio.async_mode, "async_mode doesnt exist?" | ||
assert app.socketio.async_mode == "threading", f"async_mode is {app.socketio.async_mode}" | ||
socketio_test_client = app.socketio.test_client(app) | ||
assert socketio_test_client.is_connected(), "socketio_test_client is not connected?" | ||
socketio_test_client.emit('my_event', {'data': 'test'}) | ||
received = socketio_test_client.get_received() | ||
assert len(received) == 0, "Response received from socketio" | ||
|
||
|
||
@pytest.mark.dependency(depends=["test_socketio_exists_and_works"]) | ||
@pytest.mark.skipif(condition=testLevel < 1, reason="Not doing lvl 1 tests") | ||
def test_handle_errors_and_logging(app): | ||
assert app.handle_errors_and_logging, "handle_errors_and_logging doesnt exist?" | ||
assert callable(app.handle_errors_and_logging), "handle_errors_and_logging is not callable?" | ||
assert app.handle_errors_and_logging(Exception("Test Exception")) is False, "handle_errors_and_logging did not return False?" | ||
|
||
|
||
@pytest.mark.dependency(depends=["test_handle_errors_and_logging"]) | ||
@pytest.mark.skipif(condition=testLevel < 1, reason="Not doing lvl 1 tests") | ||
def test_static_loading_for_client(app): | ||
assert app.static_folder, "static_folder doesnt exist?" | ||
assert os.path.join("client","dist") in app.static_folder, f"static_folder is {app.static_folder}" | ||
assert os.path.exists(app.static_folder), f"static_folder {app.static_folder} does not exist" | ||
|
||
|
||
@pytest.mark.dependency(depends=["test_static_loading_for_client"]) | ||
@pytest.mark.skipif(condition=testLevel < 1, reason="Not doing lvl 1 tests") | ||
def test_index_html_exists_in_the_static_files(app): | ||
assert os.path.exists(os.path.join(app.static_folder, "index.html")), f"index.html does not exist in {app.static_folder}" | ||
|
||
|
||
@pytest.mark.dependency(depends=["test_index_html_exists_in_the_static_files"]) | ||
@pytest.mark.skipif(condition=testLevel < 1, reason="Not doing lvl 1 tests") | ||
def test_main_view_response_is_200(app): | ||
with app.test_client() as client: | ||
response = client.get('/') | ||
assert response.status_code == 200, f"Response status code is {response.status_code}" | ||
assert response.data, "Response data is empty?" | ||
assert b'<!DOCTYPE html>' in response.data, "Response data does not contain <!DOCTYPE html>?" | ||
assert b'<html' in response.data, "Response data does not contain <html>?" | ||
assert b'<head>' in response.data, "Response data does not contain <head>?" | ||
assert b'<title>' in response.data, "Response data does not contain <title>?" | ||
assert b'<body>' in response.data, "Response data does not contain <body>?" | ||
assert b'<div id="app">' in response.data, 'Response data does not contain <div id="app">?' | ||
assert b'<script type="module" crossorigin src=' in response.data, 'Response data does not contain <script type="module" crossorigin src=?' | ||
assert b'<link rel="stylesheet" crossorigin href=' in response.data, 'Response data does not contain <link rel="stylesheet" crossorigin href=?' | ||
assert b'</body>' in response.data, "Response data does not contain </body>?" | ||
assert b'</html>' in response.data, "Response data does not contain </html>?" | ||
|
||
# @pytest.mark.skipif(condition=testLevel < 1, reason="Not doing lvl 1 tests") | ||
# def test_queue_view_response(app): | ||
# with app.test_client() as client: | ||
# response = client.get('/queue') | ||
# assert response.status_code == 200, f"Response status code is {response.status_code}" | ||
# assert response.data, "Response data is empty?" | ||
# assert b'<!DOCTYPE html>' in response.data, "Response data does not contain <!DOCTYPE html>?" | ||
# assert b'<html' in response.data, "Response data does not contain <html>?" | ||
# assert b'<head>' in response.data, "Response data does not contain <head>?" | ||
# assert b'<title>' in response.data, "Response data does not contain <title>?" | ||
# assert b'<body>' in response.data, "Response data does not contain <body>?" | ||
# assert b'<div id="app">' in response.data, 'Response data does not contain <div id="app">?' | ||
# assert b'<script type="module" crossorigin src=' in response.data, 'Response data does not contain <script type="module" crossorigin src=?' | ||
# assert b'<link rel="stylesheet" crossorigin href=' in response.data, 'Response data does not contain <link rel="stylesheet" crossorigin href=?' | ||
# assert b'</body>' in response.data, "Response data does not contain </body>?" | ||
# assert b'</html>' in response.data, "Response data does not contain </html>?" | ||
# | ||
# @pytest.mark.skipif(condition=testLevel < 1, reason="Not doing lvl 1 tests") | ||
# def test_registered_view_response(app): | ||
# with app.test_client() as client: | ||
# response = client.get('/registration') | ||
# assert response.status_code == 200, f"Response status code is {response.status_code}" | ||
# assert response.data, "Response data is empty?" | ||
# assert b'<!DOCTYPE html>' in response.data, "Response data does not contain <!DOCTYPE html>?" | ||
# assert b'<html' in response.data, "Response data does not contain <html>?" | ||
# assert b'<head>' in response.data, "Response data does not contain <head>?" | ||
# assert b'<title>' in response.data, "Response data does not contain <title>?" | ||
# assert b'<body>' in response.data, "Response data does not contain <body>?" | ||
# assert b'<div id="app">' in response.data, 'Response data does not contain <div id="app">?' | ||
# assert b'<script type="module" crossorigin src=' in response.data, 'Response data does not contain <script type="module" crossorigin src=?' | ||
# assert b'<link rel="stylesheet" crossorigin href=' in response.data, 'Response data does not contain <link rel="stylesheet" crossorigin href=?' | ||
# assert b'</body>' in response.data, "Response data does not contain </body>?" | ||
# assert b'</html>' in response.data, "Response data does not contain </html>?" | ||
# | ||
# @pytest.mark.skipif(condition=testLevel < 1, reason="Not doing lvl 1 tests") | ||
# def test_error_view_response(app): | ||
# with app.test_client() as client: | ||
# response = client.get('/error') | ||
# assert response.status_code == 200, f"Response status code is {response.status_code}" | ||
# assert response.data, "Response data is empty?" | ||
# assert b'<!DOCTYPE html>' in response.data, "Response data does not contain <!DOCTYPE html>?" | ||
# assert b'<html' in response.data, "Response data does not contain <html>?" | ||
# assert b'<head>' in response.data, "Response data does not contain <head>?" | ||
# assert b'<title>' in response.data, "Response data does not contain <title>?" | ||
# assert b'<body>' in response.data, "Response data does not contain <body>?" | ||
# assert b'<div id="app">' in response.data, 'Response data does not contain <div id="app">?' | ||
# assert b'<script type="module" crossorigin src=' in response.data, 'Response data does not contain <script type="module" crossorigin src=?' | ||
# assert b'<link rel="stylesheet" crossorigin href=' in response.data, 'Response data does not contain <link rel="stylesheet" crossorigin href=?' | ||
# assert b'</body>' in response.data, "Response data does not contain </body>?" | ||
# assert b'</html>' in response.data, "Response data does not contain </html>?" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,56 @@ | ||
import os | ||
import pytest | ||
from Classes.Ports import Ports | ||
from Classes.Vector3 import Vector3 | ||
from parallel_test_runner import testLevel | ||
|
||
testLevelToRun = testLevel | ||
shortTest = True | ||
|
||
def __desc__(): | ||
return "Device Tests" | ||
|
||
def __repr__(): | ||
return f"test_device.py running on port {Ports.getPortByName(os.getenv('PORT'))}" | ||
|
||
@pytest.mark.dependency(depends=["test_app.py::test_main_view_response_is_200"], scope="session") | ||
@pytest.mark.skipif(condition=testLevelToRun < 1, reason="Not doing lvl 1 tests") | ||
def test_connection(app, fabricator): | ||
assert fabricator.device is not None, f"No printer connected on {fabricator.device.DESCRIPTION}" | ||
assert fabricator.device.serialConnection is not None, f"No serial connection on {fabricator.device.DESCRIPTION}" | ||
assert fabricator.device.serialConnection.isOpen(), f"Serial connection not open on {fabricator.device.DESCRIPTION}" | ||
|
||
@pytest.mark.dependency(depends=["test_connection"]) | ||
@pytest.mark.skipif(condition=testLevelToRun < 3, reason="Not doing lvl 3 tests") | ||
def test_home(app, fabricator): | ||
assert fabricator.device.home(), f"Failed to home {fabricator.device.DESCRIPTION}" | ||
|
||
@pytest.mark.dependency(depends=["test_home"]) | ||
@pytest.mark.skipif(condition=testLevelToRun < 5, reason="Not doing lvl 5 tests") | ||
def test_draw_square(app, fabricator): | ||
squarePasses = 0 | ||
for point in [Vector3(50.0, 50.0, 2.0), Vector3(200.0, 50.0, 2.0), Vector3(200.0, 150.0, 2.0), | ||
Vector3(50.0, 150.0, 2.0)]: | ||
squarePasses += 1 if fabricator.device.goTo(point, isVerbose=True) else 0 | ||
assert squarePasses == 4, f"Failed to draw square on {fabricator.device.DESCRIPTION}" | ||
|
||
@pytest.mark.dependency(depends=["test_home"]) | ||
@pytest.mark.skipif(condition=testLevelToRun < 5, reason="Not doing lvl 5 tests") | ||
def test_draw_octagon(app, fabricator): | ||
octagonPasses = 0 | ||
for point in [Vector3(50.0, 100.0, 2.0), Vector3(100.0, 50.0, 2.0), Vector3(150.0, 50.0, 2.0), | ||
Vector3(200.0, 100.0, 2), Vector3(200.0, 150.0, 2.0), Vector3(150.0, 200.0, 2), | ||
Vector3(100.0, 200.0, 2.0), Vector3(50.0, 150.0, 2.0)]: | ||
octagonPasses += 1 if fabricator.device.goTo(point) else 0 | ||
assert octagonPasses == 8, f"Failed to draw octagon on {fabricator.device.DESCRIPTION}" | ||
|
||
@pytest.mark.dependency(depends=["test_home"]) | ||
@pytest.mark.skipif(condition=testLevelToRun < 5, reason="Not doing lvl 5 tests") | ||
def test_go_to_center(app, fabricator): | ||
assert fabricator.device.goTo(Vector3(125.0, 100.0, 2.0)), f"Failed to go to location on {fabricator.device.DESCRIPTION}" | ||
|
||
@pytest.mark.dependency(depends=["test_go_to_center"]) | ||
@pytest.mark.skipif(condition=testLevelToRun < 5, reason="Not doing lvl 5 tests") | ||
def test_draw_circle(app, fabricator): | ||
assert fabricator.device.sendGcode(b"G2 X125 Y100 I25 J0\n"), f"Failed to draw circle on {fabricator.device.DESCRIPTION}" | ||
assert fabricator.device.sendGcode(b"G2 X125 Y100 I-25 J0\n"), f"Failed to draw circle on {fabricator.device.DESCRIPTION}" |
Oops, something went wrong.