From b76f906ddc7aea1c953ce252bd046074384e9ddf Mon Sep 17 00:00:00 2001 From: "Leslie P. Polzer" Date: Tue, 18 Nov 2025 11:03:46 +0800 Subject: [PATCH] Skip tests gracefully without MPQ assets --- test/inv_test.cpp | 17 +++++++-- test/main.cpp | 79 +++++++++++++++++++++++++++++++++++++++++ test/pack_test.cpp | 18 ++++++++-- test/player_test.cpp | 9 +++-- test/timedemo_test.cpp | 5 +-- test/vendor_test.cpp | 15 +++++++- test/writehero_test.cpp | 5 +-- 7 files changed, 134 insertions(+), 14 deletions(-) diff --git a/test/inv_test.cpp b/test/inv_test.cpp index ca9ef71ae..c32119c4e 100644 --- a/test/inv_test.cpp +++ b/test/inv_test.cpp @@ -9,12 +9,17 @@ namespace devilution { namespace { +constexpr const char MissingMpqAssetsSkipReason[] = "MPQ assets (spawn.mpq or DIABDAT.MPQ) not found - skipping test suite"; + class InvTest : public ::testing::Test { public: void SetUp() override { Players.resize(1); MyPlayer = &Players[0]; + if (missingMpqAssets_) { + GTEST_SKIP() << MissingMpqAssetsSkipReason; + } } static void SetUpTestSuite() @@ -22,16 +27,22 @@ public: LoadCoreArchives(); LoadGameArchives(); - // The tests need spawn.mpq or diabdat.mpq - // Please provide them so that the tests can run successfully - ASSERT_TRUE(HaveMainData()); + missingMpqAssets_ = !HaveMainData(); + if (missingMpqAssets_) { + return; + } InitCursor(); LoadSpellData(); LoadItemData(); } + +private: + static bool missingMpqAssets_; }; +bool InvTest::missingMpqAssets_ = false; + /* Set up a given item as a spell scroll, allowing for its usage. */ void set_up_scroll(Item &item, SpellID spell) { diff --git a/test/main.cpp b/test/main.cpp index fb2df05cf..e064bceac 100644 --- a/test/main.cpp +++ b/test/main.cpp @@ -1,9 +1,83 @@ #include +#include +#include +#include + #include "headless_mode.hpp" #include "options.h" #include "utils/paths.h" +namespace { + +// Custom listener to track and report skipped tests with reasons +class SkippedTestListener : public testing::EmptyTestEventListener { + std::unordered_map skipReasons; + int totalSkipped = 0; + + void OnTestPartResult(const testing::TestPartResult &test_part_result) override + { + if (test_part_result.skipped()) { + totalSkipped++; + std::string reason = test_part_result.message(); + if (reason.empty()) { + reason = "No reason provided"; + } + skipReasons[reason]++; + } + } + + void OnTestProgramEnd(const testing::UnitTest & /*unit_test*/) override + { + if (totalSkipped > 0) { + std::cout << "\n"; + std::cout << "========================================\n"; + std::cout << "Test Skip Summary\n"; + std::cout << "========================================\n"; + std::cout << "Total tests skipped: " << totalSkipped << "\n\n"; + + // Show skip reasons, with most specific reasons first + bool hasMpqReason = false; + bool hasNoReason = false; + int mpqSkipCount = 0; + int noReasonCount = 0; + + for (const auto &[reason, count] : skipReasons) { + if (reason.find("MPQ assets") != std::string::npos) { + hasMpqReason = true; + mpqSkipCount += count; + continue; + } + if (reason == "No reason provided") { + hasNoReason = true; + noReasonCount += count; + continue; + } + std::cout << " • " << count << " test" << (count > 1 ? "s" : "") << " skipped: " << reason << "\n"; + } + + // Combine MPQ-related skips for clearer output + if (hasMpqReason) { + int totalMpqRelated = mpqSkipCount + (hasNoReason ? noReasonCount : 0); + std::cout << " • " << totalMpqRelated << " test" << (totalMpqRelated > 1 ? "s" : "") + << " skipped: MPQ assets (spawn.mpq or DIABDAT.MPQ) not found\n"; + if (hasNoReason && noReasonCount > 0) { + std::cout << " (" << noReasonCount << " test" << (noReasonCount > 1 ? "s" : "") + << " automatically skipped due to test suite setup failure)\n"; + } + } else if (hasNoReason) { + // Only "No reason provided" - show it as-is + std::cout << " • " << noReasonCount << " test" << (noReasonCount > 1 ? "s" : "") + << " skipped: " << "No reason provided" << "\n"; + } + + std::cout << "========================================\n"; + } + } +}; + +} // namespace + int main(int argc, char **argv) { // Disable error dialogs. @@ -20,5 +94,10 @@ int main(int argc, char **argv) #endif testing::InitGoogleTest(&argc, argv); + + // Add custom listener to track and report skipped tests + testing::TestEventListeners &listeners = testing::UnitTest::GetInstance()->listeners(); + listeners.Append(new SkippedTestListener()); + return RUN_ALL_TESTS(); } diff --git a/test/pack_test.cpp b/test/pack_test.cpp index 84a8558b6..23771d6fd 100644 --- a/test/pack_test.cpp +++ b/test/pack_test.cpp @@ -15,6 +15,8 @@ namespace devilution { namespace { +constexpr const char MissingMpqAssetsSkipReason[] = "MPQ assets (spawn.mpq or DIABDAT.MPQ) not found - skipping test suite"; + void SwapLE(ItemPack &pack) { pack.iSeed = Swap32LE(pack.iSeed); @@ -894,6 +896,10 @@ class NetPackTest : public ::testing::Test { public: void SetUp() override { + if (missingMpqAssets_) { + GTEST_SKIP() << MissingMpqAssetsSkipReason; + } + Players.resize(2); MyPlayer = &Players[0]; gbIsMultiplayer = true; @@ -976,9 +982,10 @@ public: LoadCoreArchives(); LoadGameArchives(); - // The tests need spawn.mpq or diabdat.mpq - // Please provide them so that the tests can run successfully - ASSERT_TRUE(HaveMainData()); + missingMpqAssets_ = !HaveMainData(); + if (missingMpqAssets_) { + return; + } SetHellfireState(false); InitCursor(); @@ -987,8 +994,13 @@ public: LoadMonsterData(); LoadItemData(); } + +private: + static bool missingMpqAssets_; }; +bool NetPackTest::missingMpqAssets_ = false; + bool TestNetPackValidation() { PlayerNetPack packed; diff --git a/test/player_test.cpp b/test/player_test.cpp index fb5ed31d9..7a4cbed50 100644 --- a/test/player_test.cpp +++ b/test/player_test.cpp @@ -86,7 +86,9 @@ TEST(Player, PM_DoGotHit) { LoadCoreArchives(); LoadGameArchives(); - ASSERT_TRUE(HaveMainData()); + if (!HaveMainData()) { + GTEST_SKIP() << "MPQ assets (spawn.mpq or DIABDAT.MPQ) not found - skipping test"; + } LoadPlayerDataFiles(); Players.resize(1); @@ -191,8 +193,9 @@ TEST(Player, CreatePlayer) LoadGameArchives(); // The tests need spawn.mpq or diabdat.mpq - // Please provide them so that the tests can run successfully - ASSERT_TRUE(HaveMainData()); + if (!HaveMainData()) { + GTEST_SKIP() << "MPQ assets (spawn.mpq or DIABDAT.MPQ) not found - skipping test"; + } LoadPlayerDataFiles(); LoadMonsterData(); diff --git a/test/timedemo_test.cpp b/test/timedemo_test.cpp index 11888963c..b379ecc3e 100644 --- a/test/timedemo_test.cpp +++ b/test/timedemo_test.cpp @@ -48,8 +48,9 @@ void RunTimedemo(std::string timedemoFolderName) LoadGameArchives(); // The tests need spawn.mpq or diabdat.mpq - // Please provide them so that the tests can run successfully - ASSERT_TRUE(HaveMainData()); + if (!HaveMainData()) { + GTEST_SKIP() << "MPQ assets (spawn.mpq or DIABDAT.MPQ) not found - skipping test"; + } const std::string unitTestFolderCompletePath = paths::BasePath() + "test/fixtures/timedemo/" + timedemoFolderName; paths::SetPrefPath(unitTestFolderCompletePath); diff --git a/test/vendor_test.cpp b/test/vendor_test.cpp index b6d067d9b..82a4e5ee8 100644 --- a/test/vendor_test.cpp +++ b/test/vendor_test.cpp @@ -16,6 +16,7 @@ using ::testing::AnyOf; using ::testing::Eq; constexpr int SEED = 75357; +constexpr const char MissingMpqAssetsSkipReason[] = "MPQ assets (spawn.mpq or DIABDAT.MPQ) not found - skipping test suite"; std::string itemtype_str(ItemType type); std::string misctype_str(item_misc_id type); @@ -78,6 +79,10 @@ class VendorTest : public ::testing::Test { public: void SetUp() override { + if (missingMpqAssets_) { + GTEST_SKIP() << MissingMpqAssetsSkipReason; + } + Players.resize(1); MyPlayer = &Players[0]; gbIsHellfire = false; @@ -90,13 +95,21 @@ public: { LoadCoreArchives(); LoadGameArchives(); - ASSERT_TRUE(HaveMainData()); + missingMpqAssets_ = !HaveMainData(); + if (missingMpqAssets_) { + return; + } LoadPlayerDataFiles(); LoadItemData(); LoadSpellData(); } + +private: + static bool missingMpqAssets_; }; +bool VendorTest::missingMpqAssets_ = false; + std::string itemtype_str(ItemType type) { const std::string ITEM_TYPES[] = { diff --git a/test/writehero_test.cpp b/test/writehero_test.cpp index 10584f7fe..2d10f9f5f 100644 --- a/test/writehero_test.cpp +++ b/test/writehero_test.cpp @@ -368,8 +368,9 @@ TEST(Writehero, pfile_write_hero) LoadGameArchives(); // The tests need spawn.mpq or diabdat.mpq - // Please provide them so that the tests can run successfully - ASSERT_TRUE(HaveMainData()); + if (!HaveMainData()) { + GTEST_SKIP() << "MPQ assets (spawn.mpq or DIABDAT.MPQ) not found - skipping test"; + } const std::string savePath = paths::BasePath() + "multi_0.sv"; paths::SetPrefPath(paths::BasePath());