Writes, runs and debugs QtPass Qt Test suites under tests/auto, adds new tst_ suites, isolates settings, and checks coverage and ASan leaks. Use when asked to write tests, add a test, run tests or make check, fix a failing test, find which suite covers a class, measure coverage, hunt leaks with sanitizers, or set up test fixtures.
77
97%
Does it follow best practices?
Run evals on this skill
Adds up to 20 points to the overall score
Passed
No findings from the security scan
QtPass tests use Qt Test. Each suite is a separate binary in
tests/auto/<suite>/, linked against the static library built from src/.
The suite list is SUBDIRS in tests/auto/auto.pro.
For the full suite inventory (which suite covers which class, platform exclusions, shared helpers), read references/suites.md. For longer patterns (getters with defaults, path comparison, settings isolation details, reading ASan output), read references/patterns.md.
make check # build and run every suite
QT_QPA_PLATFORM=offscreen make check # headless, as CI runs it
./tests/auto/util/tst_util # one suite
./tests/auto/util/tst_util normalizeFolderPath # one test function
./tests/auto/util/tst_util -v2 # verbose: every QVERIFY/QCOMPARE
./tests/auto/util/tst_util -vs # also log every emitted signal
./tests/auto/util/tst_util -functions # list the test functionsCoverage:
qmake6 -r CONFIG+=coverage
make -j4
make check
make lcovmake check. If any suite fails, read the failing function's output
with -v2, fix the code or the test, and re-run until every suite passes.
Do not commit with a failing suite.QScopedPointer, delete,
dialogs, setWindowFlags), also run the ASan build below and fix every
report before committing.clang-format --style=file -i on the files you changed. Lint and CI
details are in the qtpass-linting skill.// SPDX-FileCopyrightText: 2026 Your Name
// SPDX-License-Identifier: GPL-3.0-or-later
#include <QtTest>
#include "../../../src/mymodule.h"
#include "../testsettings.h"
class tst_mymodule : public QObject {
Q_OBJECT
private Q_SLOTS:
void initTestCase();
void processReturnsExpected();
void processEmptyInput();
};
void tst_mymodule::initTestCase() {
// First statement, before anything touches QtPassSettings.
isolateTestSettings();
}
void tst_mymodule::processReturnsExpected() {
QCOMPARE(MyModule::process("input"), QStringLiteral("expected"));
}
void tst_mymodule::processEmptyInput() {
QVERIFY(MyModule::process("").isEmpty());
}
QTEST_MAIN(tst_mymodule)
#include "tst_mymodule.moc"Drop isolateTestSettings() only if the code under test never reads
settings. Suites that need a Pass object without a backend derive from
NullPass in ../testpass.h.
!include(../auto.pri) { error("Couldn't find the auto.pri file!") }
SOURCES += tst_mymodule.cpptests/auto/auto.pri handles linking libqtpass.a, the include path, the
Windows resource and linker cap, and the tst_ target prefix. Do not list
library headers in HEADERS (their moc output is already in the library, and
listing them mocs them twice) and do not compile library sources into the
suite. Add only what the suite needs beyond that (the locale suite embeds
the translations, for example).
tests/auto/<name>/ with <name>.pro and tst_<name>.cpp.<name> to SUBDIRS in tests/auto/auto.pro. If it cannot run on
Windows, add it under !win32: as integration is.qmake6 -r && make -j4, then run make check and fix
failures until it passes.No per-suite qtpass.plist or artwork/ link is needed: qtpass.pri anchors
the macOS bundle icon and plist to the repository root.
tst_<name>.cpp, class tst_<name>, functions that say what
they check (parseColonInValue, getGpgIdPathSubfolder).QCOMPARE(actual, expected) for values (it prints both),
QVERIFY2(cond, msg) when the condition needs an explanation, QVERIFY
otherwise. QSKIP for a case that cannot run on this platform.|| in an assertion: set up the state so there is one correct answer.getter(!value), getter(-1), getter(QString())), or a broken
setter still passes.#ifndef Q_OS_WIN (or #ifdef) inside
the test function, or QSKIP.QDir::cleanPath() on both sides.QTemporaryDir, checked with isValid(); never write into
the source tree or $HOME.testkey123, example.com,
/usr/bin/pass, not strings shaped like real API keys.canConvert<QString>() over comparing
metaType().id().Worked examples of these are in references/patterns.md.
Use ASan and LSan, not valgrind (valgrind is far slower, trips over Qt 6 on a current glibc, and needs suppressions). Build in a separate directory or a fresh worktree, since sanitizer objects do not mix with a normal build:
qmake6 "CONFIG+=debug sanitizer sanitize_address"
make -j8
ASAN_OPTIONS=detect_leaks=1 QT_QPA_PLATFORM=offscreen make checkThe suite ran clean with no suppressions as of 2026-09-16, so any report is a regression to fix, then re-run until clean. How to read a report is in references/patterns.md.
The untrusted-input parsers also have libFuzzer targets in tests/fuzz/; see
the repository CLAUDE.md for the build and run commands.
IJHack/QtPass
47fd421
If you maintain this skill, you can claim it as your own. Once claimed, you can manage eval scenarios, bundle related skills, attach documentation or rules, and ensure cross-agent compatibility.