mudlet/test/README.md
Vadim Peretokin 669c586f62
infrastructure: rename the six tests Windows refuses to launch without elevation (#9753)
#### Brief overview of PR changes/additions
- Renames the six test executables whose filenames trip Windows' UAC
installer detection: `UpdaterChecksumTest` to
`ReleaseChecksumPairingTest`, `UpdaterPlatformAssetTest` to
`ReleasePlatformAssetTest`, `UpdaterTeardownTest` to
`NewReleaseDialogTeardownTest`, `PackageSelfUninstallTest` to
`PackageSelfRemovalTest`, `PackageUninstallSaveTeardownTest` to
`PackageRemovalSaveTeardownTest`, `ActionSelfUninstallTest` to
`ActionSelfRemovalTest`. Assertions are untouched.
- Adds a configure-time gate in `test/CMakeLists.txt` that fails with an
actionable message if any test executable name contains install, setup,
update or patch. It checks both the targets a configuration builds and
the test source filenames, so conditionally registered tests cannot slip
past it.
- Documents the naming rule in `test/README.md`.

#### Motivation for adding to Mudlet
Windows treats an unsigned executable named that way as an installer and
refuses to start it, so those six tests reported `BAD_COMMAND` for
anyone running the suite from an ordinary Windows shell - and because CI
runners are elevated, nothing caught it as more tests were added.

#### Other info (issues closed, discussion etc)
Fixes #9748

The gate was verified to fire on a target named after the guard
statement, on one in a subdirectory, on `EventDispatcherTest` (the
message names the offending substring, since "dispatch" contains
"patch"), on a test registered only under `USE_UPDATER` when configuring
with the updater off, and to fail loudly if the walk ever stops finding
executables.

**Test case:** `cmake --build build && ctest --test-dir build` - 92/92
pass; adding a test named e.g. `FooUpdateTest` fails the configure with
an explanation.

Assisted-by: Claude:claude-opus-5
2026-08-11 08:07:10 +02:00

3.5 KiB

Mudlet C++ Qt Tests

This directory contains unit tests for Mudlet's C++ codebase using the Qt Test framework.

Running Tests

Command Line

From the build directory, you can run tests using several methods:

Run all tests

# go into the build directory, wherever that might be
cd build/

# run test
ctest --verbose

Run specific tests

# Run a single test by name
ctest -R TEntityResolverTest

# Run tests matching a pattern
ctest -R "TMxp.*"

Qt Creator integration

Qt Creator provides excellent integration for running and debugging Qt tests:

Running tests from Qt Creator

  1. Open the Project: Open Mudlet's main CMakeLists.txt in Qt Creator
  2. Run tests: ToolsTestsRun All Tests

Contributing New Tests

Test Structure

All Qt tests in Mudlet follow this basic structure:

#include <QtTest/QtTest>
#include <SourceFileToTest.h>

class MyComponentTest : public QObject {
    Q_OBJECT

private slots:
    void initTestCase() {
        // Setup before all tests
    }

    void init() {
        // Setup before each test
    }

    void testBasicFunctionality() {
        // Your test implementation
        QCOMPARE(actualValue, expectedValue);
        QVERIFY(condition);
    }

    void cleanup() {
        // Cleanup after each test
    }

    void cleanupTestCase() {
        // Cleanup after all tests
    }
};

QTEST_MAIN(MyComponentTest)
#include "MyComponentTest.moc"

Adding a New Test

  1. Create Test File: Create YourTestName.cpp in the test/ directory. Keep the words install, uninstall, setup, update and patch out of the name: Windows takes an unsigned executable named that way for an installer and will not start it from an ordinary, non-elevated Windows shell. CMake rejects such a name at configure time.

  2. Implement Test Class: Follow the structure above, inheriting from QObject and using Q_OBJECT macro

  3. Add to CMakeLists.txt: Edit test/CMakeLists.txt and add:

    add_executable(YourTestName YourTestName.cpp ../src/SourceFileToTest.cpp)
    add_test(NAME YourTestName COMMAND YourTestName)
    
  4. Link Dependencies: Add any required libraries:

    target_link_libraries(YourTestName Qt6::Core Qt6::Test)
    
  5. Include Source Files: Include the source files you're testing (see existing examples)

Best Practices

  • Test Naming: Use descriptive test method names like testEntityResolutionWithStandardEntities()
  • Test Independence: Each test should be independent and not rely on other tests
  • Setup/Cleanup: Use init()/cleanup() for per-test setup, initTestCase()/cleanupTestCase() for global setup
  • Assertions: Use appropriate Qt Test macros:
    • QCOMPARE(actual, expected) for equality checks
    • QVERIFY(condition) for boolean conditions
    • QVERIFY_EXCEPTION_THROWN(expression, exception) for exception testing
  • Test Data: For data-driven tests, use QFETCH and QTest::addColumn

Example: Simple Test Implementation

#include <QtTest/QtTest>
#include <TEntityResolver.h>

class TEntityResolverTest : public QObject {
    Q_OBJECT

private slots:
    void testStandardEntities() {
        TEntityResolver resolver;

        QCOMPARE(resolver.getResolution("&nbsp;"), " ");
        QCOMPARE(resolver.getResolution("&gt;"), ">");
        QCOMPARE(resolver.getResolution("&lt;"), "<");
        QCOMPARE(resolver.getResolution("&amp;"), "&");
    }
};

QTEST_MAIN(TEntityResolverTest)
#include "TEntityResolverTest.moc"