5. Testing

The test directory contains some tests for the LAMMPS-GUI project using either the GoogleTest framework or the Python unittest framework.

5.1. Overview

The test suite uses CMake’s CTest front end to select and run the tests. Tests implemented with GoogleTest are automatically discovered and can be run individually or as a complete suite for each test program. Tests running LAMMPS-GUI itself use the “virtual frame buffer” X server (Xvfb) and are written in Python using the unittest Python module and the PyAutoGUI module

5.2. Building the Tests

Tests are built as part of the main project build when using -D ENABLE_TESTING=ON during CMake configuration (default setting is OFF). Due to technical requirements, testing is currently only enabled for native Linux builds of LAMMPS-GUI. In any other build environment, the -D ENABLE_TESTING=ON setting is ignored.

5.2.1. Quick Build

For running the tests, it is not necessary to build the documentation, so its build can be skipped during configuration.

cmake -S . -B build -D LAMMPS_GUI_USE_PLUGIN=ON -D BUILD_DOC=OFF -D ENABLE_TESTING=ON
cmake --build build --parallel 2

5.2.2. Disable Tests

Tests are disabled by default. If they have been enabled during CMake configuration they can be disabled at a later point with:

cmake -S . -B build -D ENABLE_TESTING=OFF

5.3. Running Tests

Below are some frequently used command line examples for running tests. These examples assume that LAMMPS-GUI was compiled in the folder build. CTest can also be invoked from the top of the build tree (--test-dir build); both forms work and select the same set of tests.

5.3.1. Run All Tests

ctest --test-dir build/test

5.3.2. Run Tests with Verbose Output

ctest --test-dir build/test -V

5.3.3. List Available Tests

The list of the names of all available tests can be obtained with:

ctest --test-dir build/test -N

5.3.4. Run Specific Tests

Individual tests can be selected in different ways. Most common is the use of regular expressions to select (-R) or exclude (-E) tests. It is also possible to select tests by a range of Test numbers (-I) from the -N test list output. Examples:

ctest --test-dir build/test -R MyStrdup
ctest --test-dir build/test -E Frame
ctest --test-dir build/test -I 20,25

5.4. Current Test Coverage

The test infrastructure is under active development. Currently, the test suite focuses on utility functions and command-line interface validation. Future expansion will include GUI component testing and integration tests.

5.4.1. Test Organization

Tests are organized into three main categories:

  1. Unit Tests: Using GoogleTest framework to test individual functions

  2. Command-Line Tests: Using command-line to validate basic executable behavior

  3. GUI Tests: Tests using the Python unittest framework and PyAutoGUI to run LAMMPS-GUI inside a virtual frame buffer in a “remote controlled fashion”.

5.4.2. Unit Tests

test_helpers.cpp

Comprehensive tests for functions in src/helpers.h and src/helpers.cpp. This module contains 38 test cases covering utility functions used throughout the application.

Date Comparison (dateCompare)

Tests for the dateCompare function that compares version date strings in LAMMPS date format (e.g., “22 Jul 2025”):

  • Same dates (returns 0)

  • Different years (returns positive/negative)

  • Different months (returns positive/negative)

  • Different days (returns positive/negative)

  • Full month names vs. abbreviations

  • Invalid date formats

  • Edge cases (year boundaries, month boundaries)

  • December month ordering

  • Both dates invalid

  • Dates with “- Update” suffix

Line Splitting (splitLine)

Tests for the splitLine function that parses command-line style input with proper quote handling:

  • Simple whitespace-separated tokens

  • Single-quoted strings

  • Double-quoted strings

  • Escaped quotes within strings

  • Mixed quoting styles

  • Triple-nested quotes

  • Multiple consecutive whitespace characters

  • Empty input

  • Quotes at string boundaries

  • Single word without spaces

  • Hash comment handling

  • Special characters

Executable Detection (hasExe)

Tests for the hasExe function that checks if an executable exists in PATH:

  • Common system commands (sh, ls on Unix; cmd on Windows)

  • Non-existent commands

  • Empty string input

  • bash executable

  • Platform-specific behavior (conditional compilation)

Theme Detection (isLightTheme)

Tests for the isLightTheme function that determines if the current Qt theme is light or dark:

  • Boolean return value validation

  • Consistency across calls

  • No crashes on theme query

Stdout Silencing (silenceStdout/restoreStdout)

Tests for the stdout silencing functions that redirect stdout to suppress LAMMPS library output:

  • Silencing actually suppresses stdout

  • Restoring when not silenced is a no-op

  • Idempotent silencing (calling multiple times)

  • Silencing skipped during active StdCapture

  • Capture restores silenced stdout state

  • Silence and restore preserves stdout

Directory Purging (purgeDirectory)

Tests for the purgeDirectory function that recursively removes directory contents:

  • Purging directory with files

  • Non-existent directory (no crash)

  • Empty directory

test_stdcapture.cpp

Tests for the StdCapture class in src/stdcapture.{h,cpp}, which redirects the C-level stdout file descriptor through a pipe so that LAMMPS library output can be collected and displayed in the Output window. Test cases cover:

  • Capturing simple single-line output

  • Capturing multiple lines of output

  • Behavior with empty output

  • Re-using a single StdCapture instance for several capture cycles

  • getChunk() returning incremental output while a capture is active

  • getChunk() returning an empty string when not capturing

  • Multiple successive getChunk() calls during one capture

  • endCapture() being a safe no-op when no capture is active

  • getBufferUse() reporting zero before any capture activity

  • getBufferUse() reflecting the size of the most recent chunk

  • The original stdout file descriptor being restored when capture ends

test_flagwarnings.cpp

Tests for the FlagWarnings syntax highlighter used in the Output window to flag lines beginning with WARNING or ERROR and to update a running count displayed in the summary label. Test cases cover:

  • Constructor initializes the warning count to zero

  • WARNING and ERROR lines are correctly detected

  • Normal output lines are not flagged

  • The summary QLabel is updated when warnings appear

  • Empty documents produce no spurious warnings

  • Warnings are detected when they appear at the start of a line

  • The running count is correct for multiple warnings

5.4.3. Command-Line Tests

These tests validate the lammps-gui executable behavior without starting the full GUI. They run quickly and are useful for CI/CD pipelines.

CommandLine.GetVersion

Purpose: Verify version reporting consistency

This test runs:

lammps-gui --platform offscreen -v

and validates that:

  • The executable launches successfully

  • Version output includes “LAMMPS-GUI (QT6)”

  • Version number matches the PROJECT_VERSION CMake variable

  • Process exits cleanly with status 0

Environment: OMP_NUM_THREADS=1 to ensure consistent behavior

CommandLine.HasPlugin

Purpose: Verify build configuration is reflected in help text

This test runs:

lammps-gui --platform offscreen -h

and validates that help text is consistent with CMake configuration:

  • Plugin Mode (LAMMPS_GUI_USE_PLUGIN=ON): Help text includes “-p, –pluginpath <path>” option

  • Linked Mode (LAMMPS_GUI_USE_PLUGIN=OFF): Help text omits plugin path option

Environment: OMP_NUM_THREADS=1 to ensure consistent behavior

5.4.4. GUI Tests

These tests validate LAMMPS-GUI functionality using PyAutoGUI and Xvfb (virtual frame buffer). They run the actual GUI application in a headless X server environment, allowing automated interaction and screenshot capture.

Important Note: The argument for the screen number flag -n for xvfb-run must be different for each test, so that the tests may run in parallel.

Framebuffer.CreateScreenshot (test_shooter.py)

Purpose: Test the screenshot wrapper utility that abstracts different screenshooter applications

Test File: test/test_shooter.py

This test validates the shooter wrapper script that provides a unified interface to various Linux screenshot utilities (ImageMagick’s import, magick import, xfce4-screenshooter, gnome-screenshooter).

The test runs:

xvfb-run -n 11 -s "-screen 0 1024x768x24" -w 1 python test_shooter.py

within a virtual frame buffer and validates:

ScreenshotChecks.testCreateImage
  • The shooter command executes without errors

  • A PNG file is created at the specified path

  • The image dimensions match the virtual frame buffer size (1024x768)

  • The image format is PNG

  • The screenshot captures an all-black screen (expected for empty Xvfb)

  • Specific pixel values at multiple locations are (0,0,0) RGB

Dependencies:
  • PyAutoGUI - for screen size detection

  • Pillow (PIL) - for image file validation

  • One of: ImageMagick (import or magick), xfce4-screenshooter, or gnome-screenshooter

Setup/Teardown:
  • setUp(): Removes leftover shot.png from previous runs

  • tearDown(): Cleans up shot.png after test completion

Environment: Virtual frame buffer at 1024x768x24, PYTHONUNBUFFERED=1, PYTHONDONTWRITEBYTECODE=1, OMP_NUM_THREADS=1

Framebuffer.CheckSize (test_xvfbsize.py)

Purpose: Verify PyAutoGUI functionality and Xvfb screen size configuration

Test File: test/test_xvfbsize.py

This test validates that PyAutoGUI can properly interact with the virtual frame buffer created by Xvfb, which is essential for GUI automation tests.

The test runs:

xvfb-run -n 12 -s "-screen 0 1024x768x24" -w 1 python test_xvfbsize.py

within a virtual frame buffer and validates:

PyAutoGUIChecks.testScreenSize
  • PyAutoGUI correctly detects the screen dimensions

  • Screen width is 1024 pixels

  • Screen height is 768 pixels

PyAutoGUIChecks.testMousePosition
  • PyAutoGUI can detect the mouse cursor position

  • Initial mouse position is at screen center (512, 384)

  • pyautogui.moveTo() can move cursor to absolute positions

  • pyautogui.moveRel() can move cursor by relative offsets

  • Position queries return expected coordinates after moves

Dependencies:
  • PyAutoGUI - for screen size detection and mouse control

Environment: Virtual frame buffer at 1024x768x24, PYTHONUNBUFFERED=1, PYTHONDONTWRITEBYTECODE=1, OMP_NUM_THREADS=1

Framebuffer.GUIEditorChecks (test_gui_edit.py)

Purpose: Test basic LAMMPS-GUI editor functionality using automated GUI interactions

Test File: test/test_gui_edit.py

This test validates fundamental editor operations in LAMMPS-GUI by launching the application inside a virtual frame buffer and automating user interactions with PyAutoGUI. The test uses screenshot comparison to verify visual state.

The test runs:

xvfb-run -n 13 -s "-screen 0 1024x768x24" -w 1 python test_gui_edit.py

within a virtual frame buffer and validates:

GUIEditorChecks.testExitShortcut
  • LAMMPS-GUI launches and displays a white editor background

  • The Ctrl-Q keyboard shortcut exits the application cleanly

  • The process exits with status 0

  • Screenshots confirm the window was displayed and then closed

GUIEditorChecks.testExitMenu
  • The Alt-F menu shortcut opens the File menu

  • The Q key selects the Quit entry

  • The application exits cleanly with status 0

  • Screenshots confirm expected visual state

GUIEditorChecks.testExitModCancelNo
  • Text can be typed into the editor buffer

  • Exiting with a modified buffer shows a confirmation dialog

  • The Cancel option returns to the editor without exiting

  • The No option exits without saving

Dependencies:
  • PyAutoGUI - for keyboard and mouse automation

  • Pillow (PIL) - for screenshot validation

  • A supported screenshooter application

Setup/Teardown:
  • setUp(): Launches LAMMPS-GUI, cleans up leftover test files

  • tearDown(): Terminates the LAMMPS-GUI process

Environment: Virtual frame buffer at 1024x768x24, PYTHONUNBUFFERED=1, PYTHONDONTWRITEBYTECODE=1, OMP_NUM_THREADS=1, LAMMPS_GUI=<path to executable>

5.4.5. Test Fixtures and Utilities

HelpersTest Fixture

Base test fixture that creates a QCoreApplication instance for tests that require Qt functionality. The application is created once per test suite and reused across tests for efficiency. Similar lightweight fixtures (StdCaptureTest, FlagWarningsTest) are used by the matching unit test programs.

Platform-Specific Testing

Tests use conditional compilation (#ifdef _WIN32) to adapt to platform differences in:

  • Path separators

  • Line endings

  • Available system executables

  • Default shell commands

5.4.6. Future Test Expansion

Planned additions to the test suite include:

GUI Component Tests
  • CodeEditor text manipulation

  • Syntax highlighter accuracy

  • Find/replace functionality

  • Auto-completion behavior

LAMMPS Integration Tests
  • LammpsWrapper command execution

  • Variable substitution

  • Error handling

  • Output capture

File I/O Tests
  • File opening/saving

  • Recent files management

  • Auto-save functionality

  • Data file inspection

Preferences Tests
  • Settings persistence

  • Default value initialization

  • Migration between versions

Tutorial Tests
  • Tutorial file generation

  • Directory setup

  • Resource extraction

5.5. Adding Tests

5.5.1. Create a New Test File

  1. Create a new test file in the test/ directory (e.g., test_newfile.cpp)

  2. Add the test executable to test/CMakeLists.txt:

add_executable(test_newfile
  test_newfile.cpp
  ${CMAKE_SOURCE_DIR}/src/newfile.cpp
)

target_include_directories(test_newfile PRIVATE
  ${CMAKE_SOURCE_DIR}/src
)

target_link_libraries(test_newfile
  GTest::gtest_main
  Qt6::Widgets
)

gtest_discover_tests(test_newfile)

5.5.2. Add Tests to Existing File

Add new test cases using GoogleTest macros:

TEST_F(HelpersTest, NewTestName)
{
    // Arrange
    std::string input = "test data";

    // Act
    auto result = function_to_test(input);

    // Assert
    EXPECT_EQ(result, expected_value);
}

5.6. Dependencies

  • GoogleTest: Automatically fetched via CMake FetchContent (v1.17.0)

  • Qt6: Required for Qt-dependent functions (Widgets component)

  • CTest: Part of CMake, used for test execution

5.7. Notes

  • Tests that require a Qt application context use a HelpersTest fixture that creates a QCoreApplication instance.

  • Platform-specific tests (e.g., has_exe) use conditional compilation to test appropriate commands on different operating systems.

  • The test suite is designed to be easily extended with additional test files and test cases.

  • GoogleTest is fetched automatically during CMake configuration, so no manual installation is required.

5.8. CI Integration

The test suite integrates with existing CI workflows: - Tests run as part of the standard build process when ENABLE_TESTING=ON - CTest provides standard output for CI systems - Tests can be disabled for documentation-only builds