Adds a couple of helper functions for battles to run turns, prettify outputs.
This commit is contained in:
Submodule src/BuildData updated: 9b27ad72f1...9dafa51e9d
@@ -1,6 +1,8 @@
|
||||
#ifndef POKEMONSCRIPTTESTER_BATTLEBUILDER_HPP
|
||||
#define POKEMONSCRIPTTESTER_BATTLEBUILDER_HPP
|
||||
|
||||
#include <CreatureLib/Battling/TurnChoices/AttackTurnChoice.hpp>
|
||||
#include <CreatureLib/Battling/TurnChoices/PassTurnChoice.hpp>
|
||||
#include <PkmnLib/Battling/Battle/Battle.hpp>
|
||||
#include <PkmnLib/Battling/Pokemon/CreatePokemon.hpp>
|
||||
#include <angelscript.h>
|
||||
@@ -13,11 +15,23 @@ class BattleBuilder {
|
||||
TestEnvironment* env = static_cast<TestEnvironment*>(ctx->GetUserData());
|
||||
auto lib = Globals::Library.GetValue();
|
||||
|
||||
auto mon1 = PkmnLib::Battling::CreatePokemon(lib, species1, level).Build();
|
||||
auto mon1 = PkmnLib::Battling::CreatePokemon(lib, species1, level)
|
||||
.WithEffortValues(0, 0, 0, 0, 0, 0)
|
||||
.WithIndividualValues(31, 31, 31, 31, 31, 31)
|
||||
.WithNature("hardy"_cnc)
|
||||
.WithGender(CreatureLib::Library::Gender::Male)
|
||||
.IsAllowedExperienceGain(false)
|
||||
.Build();
|
||||
auto p1 = new CreatureLib::Battling::CreatureParty(1);
|
||||
p1->SwapInto(0, mon1);
|
||||
|
||||
auto mon2 = PkmnLib::Battling::CreatePokemon(lib, species2, level).Build();
|
||||
auto mon2 = PkmnLib::Battling::CreatePokemon(lib, species2, level)
|
||||
.WithEffortValues(0, 0, 0, 0, 0, 0)
|
||||
.WithIndividualValues(31, 31, 31, 31, 31, 31)
|
||||
.WithNature("hardy"_cnc)
|
||||
.WithGender(CreatureLib::Library::Gender::Male)
|
||||
.IsAllowedExperienceGain(false)
|
||||
.Build();
|
||||
auto p2 = new CreatureLib::Battling::CreatureParty(1);
|
||||
p1->SwapInto(0, mon2);
|
||||
|
||||
@@ -40,12 +54,56 @@ class BattleBuilder {
|
||||
return battle;
|
||||
}
|
||||
|
||||
static bool UseMove(PkmnLib::Battling::Pokemon* user, const ArbUt::StringView& moveName, u8 sideTarget, u8 target) {
|
||||
auto battle = user->GetBattle();
|
||||
if (!battle.HasValue()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
auto move = Globals::Library.GetValue()->GetMoveLibrary()->TryGet(moveName);
|
||||
if (!move.has_value()) {
|
||||
return false;
|
||||
}
|
||||
auto* ctx = asGetActiveContext();
|
||||
TestEnvironment* env = static_cast<TestEnvironment*>(ctx->GetUserData());
|
||||
|
||||
auto learnedMove =
|
||||
new PkmnLib::Battling::LearnedMove(move.value(), CreatureLib::Battling::AttackLearnMethod::Unknown);
|
||||
env->AddGarbage(learnedMove);
|
||||
auto choice = new CreatureLib::Battling::AttackTurnChoice(
|
||||
user, learnedMove, CreatureLib::Battling::CreatureIndex(sideTarget, target));
|
||||
auto b = battle.GetValue()->TrySetChoice(choice);
|
||||
if (!b) {
|
||||
delete choice;
|
||||
}
|
||||
return b;
|
||||
}
|
||||
|
||||
static bool PassTurn(PkmnLib::Battling::Pokemon* user) {
|
||||
auto battle = user->GetBattle();
|
||||
if (!battle.HasValue()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
auto choice = new CreatureLib::Battling::PassTurnChoice(user);
|
||||
auto b = battle.GetValue()->TrySetChoice(choice);
|
||||
if (!b) {
|
||||
delete choice;
|
||||
}
|
||||
return b;
|
||||
}
|
||||
|
||||
public:
|
||||
static void Register(AngelScriptResolver* scriptResolver) {
|
||||
auto engine = scriptResolver->GetBuilder().GetEngine();
|
||||
Ensure(engine->RegisterGlobalFunction("Battle@ CreateSimpleBattle(uint seed, const constString&in species1, "
|
||||
"const constString&in species2, uint8 level)",
|
||||
asFUNCTION(CreateSimpleBattle), asCALL_CDECL) >= 0);
|
||||
Ensure(engine->RegisterObjectMethod("Pokemon",
|
||||
"bool UseMove(const constString&in move, uint8 side, uint8 index)",
|
||||
asFUNCTION(UseMove), asCALL_CDECL_OBJFIRST) >= 0);
|
||||
Ensure(engine->RegisterObjectMethod("Pokemon", "bool PassTurn()", asFUNCTION(PassTurn),
|
||||
asCALL_CDECL_OBJFIRST) >= 0);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -12,10 +12,7 @@ private:
|
||||
size_t Line;
|
||||
};
|
||||
|
||||
static RequirementData GetRequirementData() {
|
||||
auto* ctx = asGetActiveContext();
|
||||
TestEnvironment* env = static_cast<TestEnvironment*>(ctx->GetUserData());
|
||||
env->AssertionCount += 1;
|
||||
static RequirementData GetRequirementData(asIScriptContext* ctx) {
|
||||
auto filename = ctx->GetFunction()->GetScriptSectionName();
|
||||
auto line = ctx->GetLineNumber();
|
||||
return RequirementData{
|
||||
@@ -25,8 +22,12 @@ private:
|
||||
}
|
||||
|
||||
static bool Require(bool value) {
|
||||
auto* ctx = asGetActiveContext();
|
||||
TestEnvironment* env = static_cast<TestEnvironment*>(ctx->GetUserData());
|
||||
env->TotalRequirements += 1;
|
||||
if (!value) {
|
||||
auto data = GetRequirementData();
|
||||
env->FailedRequirements += 1;
|
||||
auto data = GetRequirementData(ctx);
|
||||
throw RequirementFailed(data.FileName, data.Line);
|
||||
}
|
||||
return true;
|
||||
@@ -41,8 +42,12 @@ private:
|
||||
}
|
||||
|
||||
static bool RequireEqualsI32(i32 expected, i32 actual) {
|
||||
auto* ctx = asGetActiveContext();
|
||||
TestEnvironment* env = static_cast<TestEnvironment*>(ctx->GetUserData());
|
||||
env->TotalRequirements += 1;
|
||||
if (expected != actual) {
|
||||
auto data = GetRequirementData();
|
||||
env->FailedRequirements += 1;
|
||||
auto data = GetRequirementData(ctx);
|
||||
GetEqualityMessage(expected, actual);
|
||||
throw RequirementFailed(data.FileName, data.Line, eqMsg);
|
||||
}
|
||||
@@ -50,8 +55,11 @@ private:
|
||||
}
|
||||
|
||||
static bool RequireEqualsString(const std::string& expected, const std::string& actual) {
|
||||
auto* ctx = asGetActiveContext();
|
||||
TestEnvironment* env = static_cast<TestEnvironment*>(ctx->GetUserData());
|
||||
if (expected != actual) {
|
||||
auto data = GetRequirementData();
|
||||
env->FailedRequirements += 1;
|
||||
auto data = GetRequirementData(ctx);
|
||||
std::string eqMsg;
|
||||
{
|
||||
std::ostringstream ss;
|
||||
|
||||
@@ -30,6 +30,9 @@ public:
|
||||
inline TestResult GetResult() const noexcept { return _result; }
|
||||
inline const std::string& GetErrorMessage() const noexcept { return _errorMessage; }
|
||||
|
||||
inline size_t GetTotalRequirements() const noexcept { return _env->TotalRequirements; }
|
||||
inline size_t GetFailedRequirements() const noexcept { return _env->FailedRequirements; }
|
||||
|
||||
private:
|
||||
std::string _name;
|
||||
asIScriptFunction* _function;
|
||||
|
||||
@@ -2,7 +2,8 @@
|
||||
#define POKEMONSCRIPTTESTER_TESTENVIRONMENT_HPP
|
||||
|
||||
struct TestEnvironment {
|
||||
size_t AssertionCount = 0;
|
||||
size_t TotalRequirements = 0;
|
||||
size_t FailedRequirements = 0;
|
||||
|
||||
template <typename T> void AddGarbage(T* data) { _garbage.Append(GarbageObject(data)); }
|
||||
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
#define POKEMONSCRIPTTESTER_TESTRUNNER_HPP
|
||||
|
||||
#include <PkmnLib/ScriptResolving/AngelScript/AngelScriptMetadata.hpp>
|
||||
#include "../../extern/termcolor.hpp"
|
||||
#include "Test.hpp"
|
||||
|
||||
class TestRunner {
|
||||
@@ -34,27 +35,62 @@ public:
|
||||
size_t notRunTests = 0;
|
||||
size_t successfulTests = 0;
|
||||
size_t failedTests = 0;
|
||||
|
||||
size_t totalRequirements = 0;
|
||||
size_t failedRequirements = 0;
|
||||
|
||||
for (auto& test : _tests) {
|
||||
auto result = test.second->GetResult();
|
||||
switch (result) {
|
||||
case TestResult::NotRan: notRunTests += 1; break;
|
||||
case TestResult::Success: successfulTests += 1; break;
|
||||
case TestResult::Failed: {
|
||||
std::cout << "Test '" << test.first << "' failed with message: " << std::endl;
|
||||
std::cout << termcolor::red << "Test '" << termcolor::yellow << test.first << termcolor::red
|
||||
<< "' failed with message: " << termcolor::reset << std::endl;
|
||||
std::cout << test.second->GetErrorMessage() << std::endl << std::endl;
|
||||
failedTests += 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
totalRequirements += test.second->GetTotalRequirements();
|
||||
failedRequirements += test.second->GetFailedRequirements();
|
||||
}
|
||||
|
||||
std::cout << "Ran " << successfulTests + failedTests << " tests. Passed tests: " << successfulTests
|
||||
<< ". Failed tests: " << failedTests << "." << std::endl;
|
||||
auto totalTests = successfulTests + failedTests;
|
||||
auto digitWidth = std::log10(std::max(totalTests, totalRequirements)) + 2;
|
||||
std::cout << termcolor::blue << "=====================================================================";
|
||||
for (int i = 0; i < digitWidth; ++i) {
|
||||
std::cout << "===";
|
||||
}
|
||||
std::cout << termcolor::reset << std::endl;
|
||||
|
||||
ReportResults("Test cases", digitWidth, totalTests, successfulTests, failedTests, notRunTests);
|
||||
ReportResults("Requirements", digitWidth, totalRequirements, totalRequirements - failedRequirements,
|
||||
failedRequirements, {});
|
||||
if (failedTests > 0) {
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void ReportResults(const std::string& label, double digitWidth, size_t total, size_t passed, size_t failed,
|
||||
std::optional<size_t> skipped) {
|
||||
std::cout << std::left // Left align
|
||||
<< std::setw(16) << label + ":" << std::setw(digitWidth) << total << std::setw(3) << "|";
|
||||
if (passed > 0) {
|
||||
std::cout << termcolor::green;
|
||||
}
|
||||
std::cout << std::left << std::setw(14) << "Passed:" << std::setw(digitWidth) << passed << termcolor::reset
|
||||
<< std::setw(3) << "|";
|
||||
if (failed > 0) {
|
||||
std::cout << termcolor::red;
|
||||
}
|
||||
std::cout << std::setw(14) << "Failed:" << std::setw(digitWidth) << failed << termcolor::reset;
|
||||
if (skipped.has_value()) {
|
||||
std::cout << std::setw(3) << "|" << std::setw(14) << "Skipped:" << std::setw(digitWidth) << skipped.value()
|
||||
<< std::endl;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
#endif // POKEMONSCRIPTTESTER_TESTRUNNER_HPP
|
||||
|
||||
Reference in New Issue
Block a user