A Test automation Framework to test Odyssey Linux in an automated way. To be sure, that the Quality of the System is usable for End Users. It's based on Shipwreck, but it will be expanded to Test the official Odyssey Linux ISO too. It covers the good weather path.
  • Python 58.8%
  • Shell 41.2%
Find a file
2026-10-20 21:38:33 +02:00
shipwreck-install Fixing the R2027-Alpha Release - Bugs on Bios 2026-10-20 21:38:33 +02:00
.gitignore Fixing the R2027-Alpha Release - Bugs on Bios 2026-10-20 21:38:33 +02:00
demonstration.mkv Add Initial all Oculix Test Automation Framework Files 2026-09-25 16:02:00 +02:00
demonstration.png Add Initial all Oculix Test Automation Framework Files 2026-09-25 16:02:00 +02:00
qemu-helper-script.sh Fixing the R2027-Alpha Release - Bugs on Bios 2026-10-20 21:38:33 +02:00
qemu-serial-log-analyzer.sh Bugfixing 2026-09-29 09:00:17 +02:00
README.md README.md aktualisiert 2026-09-25 19:43:49 +01:00
start-oculix-test-automation-framework.sh Fixing the R2027-Alpha Release - Bugs on Bios 2026-10-20 21:38:33 +02:00
teardown.sh Bugfixing 2026-09-29 09:00:17 +02:00

Oculix Test Automation Framework

Description

QEMU

Watch Video

Odyssey Linux is a Linux distribution with its own format, design decisions, and configurations.
Since the distribution is a rolling release and still very new, there isn't a large army of testers, but plenty of work to test. To meet the high quality requirements of our users, automation must be considered. This framework was created for this purpose. It is based on the Oculix software.

A brief explanation is necessary as to why Oculix was chosen as the base, because image recognition is not optimal for test automation, since any adjustment to the user interface leads to great effort - moreover, this type of automation is not extremely fast and also requires many host-based prerequisites for optimal operation. Both software requirements and configuration requirements (screen resolution) are mentioned here.

In contrast to classic automation approaches that recognize objects based on attributes, this is not possible in a virtualized environment. Odyssey Linux is to be reinstalled repeatedly, and if possible not on an SSD, as this requires massive write work and results in wear. Therefore, the approach was chosen to write Odyssey Linux into the computer's RAM each time; this methodology allows the installation to be played through hundreds of times and relatively quickly. To emulate the hardware as realistically as possible, QEMU was used.

QEMU emulates a computer and thereby offers the possibility to provide realistic "hardware". However, it is not possible to access objects in the VM from the host without running automation inside the guest system itself.
To solve this problem, Oculix was selected because it is based on image recognition - however, a proprietary recognition methodology was implemented that calculates a percentage match. To ensure that speed does not become a significant factor, image recognition was used for verifying the result - whereas the control was implemented via the keyboard wherever possible.

Instructions

To use the Oculix test automation framework, only one script needs to be started; it is operated as follows:

start-oculix-test-automation-framework.sh [ direct | ide ]

With this script, everything necessary is added fully automatically - if a software package is missing, it gets installed; if Oculix is missing, it gets downloaded; and if the Odyssey Shipwreck ISO is missing, it will also be downloaded - even if it is outdated (i.e., older than one week), a new version is downloaded via torrent. The script only aborts in the following situations and informs about the problem:

  • Insufficient RAM (<18GB)
  • Insufficient hard drive space (<5GB)
  • No X11 session available (when using Wayland)


Configuration Oculix Script: shipwreck-install.py:

--- init --------------------------------------------------------------------------------
iso_path = "odyssey-shipwreck-x86_64.iso" : Filename of the ISO - needs match with the Filename in start-oculix-test-automation-framework.sh
script = "../qemu-helper-script.sh" : Script which starts QEMU
teardownscript = "../teardown.sh" : Saves the Log from the RAM
shortwait = 2 : Wait Interval in Seconds
longwait = 20 : Wait Interval in Seconds
bootwait = 120 : Wait Interval in Seconds
setupwait = 600 : Wait Interval in Seconds
defaultlang = "ch" : Default Keyboard Layout, because the Script needs to change the Layout for correct Text Input
error = 0 : If something is broken, and the Script needs to break, set this to one [not implemented yet]
userpassword = "test" : Which password should be used for User
rootpassword = "roottest" : Which password should be used for root
hdpassword = "test" : Which password should be used for the Harddisk

--- test configuration ------------------------------------------------------------------
test_uefi_enc = "true" : This variable defines, if the Test Case 01 and 02 should be executed with UEFI Firmware + ENCryption
test_bios_enc = "true" : This variable defines, if the Test Case 01 and 02 should be executed with Bios Firmware + ENCryption
test_uefi_nonenc = "true" : This variable defines, if the Test Case 01 and 02 should be executed with UEFI Firmware + without encryption
test_bios_nonenc = "true" : This variable defines, if the Test Case 01 and 02 should be executed with Bios Firmware + without encryption

Configuration BASH Script: start-oculix-test-automation-framework.sh:

OCULIX_SCRIPT="shipwreck-install.py" : Which Oculix Script should be choosen
OCULIX_VERSION="4.0.0" : Which Oculix Version should be downloaded and used
OCULIX="oculixide-$OCULIX_VERSION-linux.jar" : Based on the Version, define the filename to check if Oculix is there
OCULIX_DOWNLOAD="https://github.com/oculix-org/Oculix/releases/download/v$OCULIX_VERSION/$OCULIX" : Where should Oculix be downloaded
ISO_FILE="odyssey-shipwreck-x86_64.iso" : Filename of the ISO - needs match with the Filename in start-oculix-test-automation-framework.sh
ISO_DOWNLOAD="https://odysseylinux.org/shipwreck.html" : Where should Shipwreck be downloaded

Important Notes

⚠️ WARNING
During execution, the computer must not be used directly; do not use mouse and keyboard. This is dangerous because if another window receives focus, it could lead to unintended changes on the host system!


Test Flow

testcase_01_bootiso(iso_path, log_path, script, uefi, bootwait, longwait, shortwait, encrypt)
Tests the ISO iso_path used and starts it in UEFI or BIOS mode (UEFI = true or false). The script is the QEMU Bash script used. Prepares the kernel to write everything to the serial interface, measures startup time, and takes inventory (existing packages on the ISO, services, network, dmesg). The variable encrypt (true/false) is needed for the log file so that the log indicates at the beginning whether the test checks disk encryption or not.

testcase_02_install_pain_login_plasma(log_path, shortwait, longwait, setupwait, uefi, encrypt, userpassword, rootpassword, hdpassword)
Performs an installation with various conditions. UEFI (true/false) specifies whether the installation is checked for UEFI or BIOS, encrypt (true/false) decides whether the hard drive is encrypted or not. The individual passwords are used for root, user, and hard drive.

Functions

Here are the functions provided to the user:

--- timestamp ---------------------------------------------------------------------------
ts_cons() : Timestamp in format: 2026-09-06 16:18:23.832 for log files
ts_filename() : Timestamp in format: 2026-09-06_161823832 for filenames

--- timer -------------------------------------------------------------------------------
start_timer(label, log_path) : Starts a timer with a label (for parallel execution of various time measurements)
stop_timer(label, log_path) : Stops the timer with exactly the same label

--- logfile writer ----------------------------------------------------------------------
write_log(message, log_path, classification) : Writes log files to log_path with the desired classification (INFO/ERROR/WARNING) in format: 2026-09-06 16:18:23.832 | [Classification] | Message

--- makes sha256 ------------------------------------------------------------------------
iso_sha256(iso_path) : This function creates a SHA256 of a file - used here to check the ISO file so that it is clarified with which installation medium the test was performed.

--- screenshot writer -------------------------------------------------------------------
_get_focus_region(log_path) : Helper function to identify the active window
capture_window(target_path, log_path) : Creates a screenshot and saves it at target_path, used for error cases

--- writing functions -------------------------------------------------------------------
write_textfield(inputfield, textstring, log_path) : Writes text into a field that was recognized via screenshot
type_char(char, log_path) : Writes a character where the focus currently is
write_text(textstring, log_path) : Writes text character-by-character where the focus currently is
paste_text(textstring, log_path) : Inserts text via paste where the focus currently is (works only in UI text fields/areas)
clear_field(inputfield, textstring, log_path) : Clears content via ctrl-a-DEL
enter() : Key press: Enter
down() : Key press: Arrow down
up() : Key press: Arrow up
toright() : Key press: Arrow right
toleft() : Key press: Arrow left
backspace() : Key press: Deletes the left character
tab() : Tabulator key
shifttab() : Tabulator and Shift, focus one back
KeyF10() : Key press: F10
DEL() : Key press: Delete
space() : Key press: Spacebar
jump_forward(count) : Focus change to the object, e.g., count=1 then one field forward, or count=5 five fields forward
jump_backward(count) : Focus change to the object, e.g., count=1 then one field back, or count=5 five fields back

--- ocr functions -----------------------------------------------------------------------
text_like(actual, expected, log_path, threshold=0.85) : String comparison, how similar are actual/expected, threshold value for True/False preset 85% - 0.85

--- compare function pass/fail ---------------------------------------------------------
check_img(image, label, log_path, threshold=0.85) : Checks whether an image is found on screen and with what similarity, threshold value for True/False preset 85% - 0.85, label is used in log file: 2026-09-25_121523555 | [INFO] | CHECK: 02:Keyboard Selection - (similarity = 99.99% expected = 98.00%) [PASS]. Note: if an image falls below the threshold, 0% similarity and [FAIL] is output

--- Open a root Terminal -----------------------------------------------------------------
open_root_terminal(log_path, longwait, shortwait, rootwithpw = "false", password = "") : Opens a terminal and executes as root via sudo bash, here distinguishing whether root already has a password defined or not (when password is supplied and rootwithpw = true)

--- Close a root Terminal ----------------------------------------------------------------
close_root_terminal(log_path) : Closes the root terminal via 'exit', 'exit'

--- Create Package Information in SerialLog ----------------------------------------------
olist(log_path) : Writes all installed packages to the serial interface

--- List Network Interfaces and their Status ---------------------------------------------
network_status(log_path) : Writes ip a to the serial interface and queries curl http://detectportal.firefox.com/canonical.html

--- List all Services and their Status ---------------------------------------------------
service_status(log_path) : Writes all services and their status to the serial interface

--- dmesg to Serial Log ------------------------------------------------------------------
dmesg(log_path) : Writes dmesg to the serial interface

--- oupdate to Serial Log ----------------------------------------------------------------
oupdate(log_path) : Performs an operating system update and writes the result to the serial interface

--- Go Back to Initial ------------------------------------------------------------------
teardown(teardownscript, defaultlang, log_dir, log_path) : Copies the serial interface logs from RAM into the log_path directory, or executes teardown.sh