Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add integration tests #12

Merged
merged 5 commits into from
Jun 13, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
41 changes: 41 additions & 0 deletions .github/workflows/integration-tests.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
name: Integration Tests
on: [push, pull_request]

jobs:

testing:
runs-on: ${{ matrix.os }}
strategy:
matrix:
os: [ubuntu-latest]
python-version: [3.6, 3.7, 3.8]
env:
DISPLAY: ':99.0'

steps:
- name: Get repository
uses: actions/checkout@v2

- name: Set up Python ${{ matrix.python-version }}
uses: actions/setup-python@v2
with:
python-version: ${{ matrix.python-version }}

- name: setup ${{ matrix.os }}
run: |
sudo apt install libxkbcommon-x11-0 libxcb-icccm4 libxcb-image0 libxcb-keysyms1 libxcb-randr0 libxcb-render-util0 libxcb-xinerama0 libxcb-xfixes0
/sbin/start-stop-daemon --start --quiet --pidfile /tmp/custom_xvfb_99.pid --make-pidfile --background --exec /usr/bin/Xvfb -- :99 -screen 0 1920x1200x24 -ac +extension GLX

- name: Install freeglut
run: |
sudo apt-get install freeglut3 freeglut3-dev

- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install flake8 pytest
pip install -r requirements.txt

- name: Test with pytest
run: |
python -m pytest tests/integration/
25 changes: 11 additions & 14 deletions .github/workflows/unit-tests.yml
Original file line number Diff line number Diff line change
@@ -1,40 +1,37 @@
# This workflow will install Python dependencies, run tests and lint with a single version of Python
# For more information see: https://help.github.com/actions/language-and-framework-guides/using-python-with-github-actions

name: Tests

on:
push:
branches: [ main ]
pull_request:
branches: [ main ]
name: Unit Tests
on: [push, pull_request]

jobs:
build:

testing:
runs-on: ${{ matrix.os }}
strategy:
matrix:
os: [ubuntu-latest, macos-latest, windows-latest]
python-version: [3.6, 3.7, 3.8]

steps:
- uses: actions/checkout@v2
- name: Get repository
uses: actions/checkout@v2

- name: Set up Python 3.8
uses: actions/setup-python@v2
with:
python-version: ${{ matrix.python-version }}

- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install flake8 pytest
pip install -r requirements.txt

- name: Lint with flake8
run: |
# stop the build if there are Python syntax errors or undefined names
flake8 . --count --select=E9,F63,F7,F82 --show-source --statistics
# exit-zero treats all errors as warnings. The GitHub editor is 127 chars wide
flake8 . --count --exit-zero --max-complexity=10 --max-line-length=127 --statistics

- name: Test with pytest
run: |
python -m pytest tests/
python -m pytest tests/unit/
2 changes: 1 addition & 1 deletion labelCloud/control/bbox_controller.py
Original file line number Diff line number Diff line change
Expand Up @@ -261,7 +261,7 @@ def update_all(self):
@has_active_bbox_decorator
def update_z_dial(self):
self.view.dial_zrotation.blockSignals(True) # To brake signal loop
self.view.dial_zrotation.setValue(self.get_active_bbox().get_z_rotation())
self.view.dial_zrotation.setValue(int(self.get_active_bbox().get_z_rotation()))
self.view.dial_zrotation.blockSignals(False)

def update_curr_class(self):
Expand Down
3 changes: 2 additions & 1 deletion requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,5 @@ numpy~=1.19.4
PyQt5~=5.15.2
PyOpenGL~=3.1.5
open3d~=0.11.2
pytest~=6.2.2
pytest~=6.2.2
pytest-qt~=4.0.1
39 changes: 39 additions & 0 deletions tests/integration/conftest.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
import os
import sys

import pytest


def pytest_configure(config):
os.chdir("../labelCloud")
print(f"Set working directory to {os.getcwd()}.")

sys.path.insert(0, "labelCloud")
print(f"Added labelCloud to Python path.")

import app # preventing circular import


@pytest.fixture
def startup_pyqt(qtbot, qapp):
from control.controller import Controller
from view.gui import GUI

# Setup Model-View-Control structure
control = Controller()
view = GUI(control)
qtbot.addWidget(view)
qtbot.addWidget(view.glWidget)

# Install event filter to catch user interventions
qapp.installEventFilter(view)

# Start GUI
view.show()
return view, control


@pytest.fixture
def bbox():
from model.bbox import BBox
return BBox(cx=0, cy=0, cz=0, length=3, width=2, height=1)
114 changes: 114 additions & 0 deletions tests/integration/test_gui.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
import os
from PyQt5 import QtCore
from PyQt5.QtWidgets import QAbstractSlider

from control.config_manager import config


def test_gui(qtbot, startup_pyqt):
view, controller = startup_pyqt

assert len(controller.pcd_manager.pcds) > 0
os.remove("labels/exemplary.json")
assert len(os.listdir("labels")) == 0
qtbot.mouseClick(view.button_next_pcd, QtCore.Qt.LeftButton, delay=0)
assert len(os.listdir("labels")) == 1

bbox = controller.bbox_controller.bboxes[0]
bbox.center = (0, 0, 0)
controller.bbox_controller.set_active_bbox(0)
qtbot.mouseClick(view.button_right, QtCore.Qt.LeftButton, delay=0)
qtbot.mouseClick(view.button_up, QtCore.Qt.LeftButton, delay=0)
qtbot.mouseClick(view.button_backward, QtCore.Qt.LeftButton, delay=0)
assert bbox.center == (0.03, 0.03, 0.03)

view.close()


def test_bbox_control_with_buttons(qtbot, startup_pyqt, bbox):
view, controller = startup_pyqt

# Prepare test bounding box
controller.bbox_controller.bboxes = [bbox]
old_length, old_width, old_height = bbox.get_dimensions()
controller.bbox_controller.set_active_bbox(0)

# Translation
translation_step = config.getfloat("LABEL", "std_translation")
qtbot.mouseClick(view.button_right, QtCore.Qt.LeftButton, delay=0)
qtbot.mouseClick(view.button_up, QtCore.Qt.LeftButton, delay=0)
qtbot.mouseClick(view.button_backward, QtCore.Qt.LeftButton, delay=0)
assert bbox.center == (translation_step, translation_step, translation_step)
qtbot.mouseClick(view.button_left, QtCore.Qt.LeftButton, delay=0)
qtbot.mouseClick(view.button_down, QtCore.Qt.LeftButton, delay=0)
qtbot.mouseClick(view.button_forward, QtCore.Qt.LeftButton)
print("BBOX: %s" % [str(c) for c in bbox.get_center()])
assert bbox.center == (0.00, 0.00, 0.00)

# Scaling
scaling_step = config.getfloat("LABEL", "std_scaling")
qtbot.mouseClick(view.button_incr_dim, QtCore.Qt.LeftButton)
assert bbox.length == old_length + scaling_step
assert bbox.width == old_width / old_length * bbox.length
assert bbox.height == old_height / old_length * bbox.length

# Rotation
# TODO: Make dial configureable?
view.dial_zrotation.triggerAction(QAbstractSlider.SliderSingleStepAdd)
assert bbox.z_rotation == 1
view.dial_zrotation.triggerAction(QAbstractSlider.SliderPageStepAdd)
assert bbox.z_rotation == 11

view.close()


def test_bbox_control_with_keyboard(qtbot, startup_pyqt, qapp, bbox):
view, controller = startup_pyqt

# Prepare test bounding box
controller.bbox_controller.bboxes = [bbox]
controller.bbox_controller.set_active_bbox(0)

# Translation
translation_step = config.getfloat("LABEL", "std_translation")
for letter in "dqw":
qtbot.keyClick(view, letter)
assert bbox.center == (translation_step, translation_step, translation_step)
translation_step = config.getfloat("LABEL", "std_translation")
for letter in "aes":
qtbot.keyClick(view, letter)
assert bbox.center == (0, 0, 0)

for key in [QtCore.Qt.Key_Right, QtCore.Qt.Key_Up, QtCore.Qt.Key_PageUp]:
qtbot.keyClick(view, key)
assert bbox.center == (translation_step, translation_step, translation_step)
for key in [QtCore.Qt.Key_Left, QtCore.Qt.Key_Down, QtCore.Qt.Key_PageDown]:
qtbot.keyClick(view, key)
assert bbox.center == (0, 0, 0)

# Rotation
rotation_step = config.getfloat("LABEL", "std_rotation")
config.set("USER_INTERFACE", "z_rotation_only", "False")
qtbot.keyClick(view, "y")
assert bbox.z_rotation == rotation_step
qtbot.keyClick(view, "x")
assert bbox.z_rotation == 0
qtbot.keyClick(view, QtCore.Qt.Key_Comma)
assert bbox.z_rotation == rotation_step
qtbot.keyClick(view, QtCore.Qt.Key_Period)
assert bbox.z_rotation == 0
qtbot.keyClick(view, "c")
assert bbox.y_rotation == rotation_step
qtbot.keyClick(view, "v")
assert bbox.y_rotation == 0
qtbot.keyClick(view, "b")
assert bbox.x_rotation == rotation_step
qtbot.keyClick(view, "n")
assert bbox.x_rotation == 0

# Shortcuts
qtbot.keyClick(view, QtCore.Qt.Key_Delete)
assert len(controller.bbox_controller.bboxes) == 0
assert controller.bbox_controller.get_active_bbox() is None

view.close()
41 changes: 41 additions & 0 deletions tests/integration/test_labeling.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
import pytest
from PyQt5 import QtCore
from PyQt5.QtCore import QPoint

from control.config_manager import config
from model.bbox import BBox


def test_picking_mode(qtbot, startup_pyqt):
view, control = startup_pyqt
control.bbox_controller.bboxes = []

qtbot.mouseClick(view.button_activate_picking, QtCore.Qt.LeftButton, delay=1000)
qtbot.mouseClick(view.glWidget, QtCore.Qt.LeftButton, pos=QPoint(500, 500), delay=1000)

assert len(control.bbox_controller.bboxes) == 1
new_bbox = control.bbox_controller.bboxes[0]
assert new_bbox.center == tuple(pytest.approx(x, 0.01) for x in [-0.2479, -0.2245, 0.0447])

assert new_bbox.length == config.getfloat("LABEL", "std_boundingbox_length")
assert new_bbox.width == config.getfloat("LABEL", "std_boundingbox_width")
assert new_bbox.height == config.getfloat("LABEL", "std_boundingbox_height")
assert new_bbox.z_rotation == new_bbox.y_rotation == new_bbox.x_rotation == 0


def test_spanning_mode(qtbot, startup_pyqt):
view, control = startup_pyqt
control.bbox_controller.bboxes = []
config.set("USER_INTERFACE", "z_rotation_only", "True")

qtbot.mouseClick(view.button_activate_spanning, QtCore.Qt.LeftButton, delay=10)
qtbot.mouseClick(view.glWidget, QtCore.Qt.LeftButton, pos=QPoint(431, 475), delay=20)
qtbot.mouseClick(view.glWidget, QtCore.Qt.LeftButton, pos=QPoint(506, 367), delay=20)
qtbot.mouseClick(view.glWidget, QtCore.Qt.LeftButton, pos=QPoint(572, 439), delay=20)
qtbot.mouseClick(view.glWidget, QtCore.Qt.LeftButton, pos=QPoint(607, 556), delay=20)

assert len(control.bbox_controller.bboxes) == 1
new_bbox: BBox = control.bbox_controller.bboxes[0]
assert new_bbox.center == tuple(pytest.approx(x, 0.01) for x in [-0.2100, -0.2348, 0.0568])
assert new_bbox.get_dimensions() == tuple(pytest.approx(x, 0.01) for x in [0.7344, 0.5305, 0.1212])
assert new_bbox.get_rotations() == tuple(pytest.approx(x % 360, 0.5) for x in [0, 0, 55.2205])
4 changes: 0 additions & 4 deletions tests/preparation.py

This file was deleted.

12 changes: 12 additions & 0 deletions tests/unit/conftest.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import os
import sys


def pytest_configure(config):
os.chdir("../labelCloud")
print(f"Set working directory to {os.getcwd()}.")

sys.path.insert(0, "labelCloud")
print(f"Added labelCloud to Python path.")

import app # preventing circular import
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@
import json
import os
import pytest
import preparation

from model.bbox import BBox
from control.label_manager import LabelManager
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import os

import pytest
import preparation
from control.label_manager import LabelManager


Expand Down