提问人:Max 提问时间:10/7/2023 最后编辑:Max 更新时间:10/16/2023 访问量:36
使用Junit4进行基于libgdx/ECS的游戏测试。如果一起执行,测试将失败
Using Junit4 for game tests based on libgdx/ECS. Tests failing if executed together
问:
长话短说:我正在使用 libgdx/ECS(实体-组件-系统)开发一个小游戏,现在我多次遇到我更改代码的问题,然后其他一些行为无法按预期工作(例如,单位无法再移动到目标位置)。
为了避免将来出现此类问题,我的想法是使用 junit4 创建简单的游戏测试。设置完所有内容后,我现在遇到了一个奇怪的问题,即如果我单独执行测试用例,它们就会通过。一旦我尝试将它们一起运行,它们就会失败。
在 @BeforeClass 方法中,我创建了 libgdx “world”,加载引擎并添加了测试所需的所有系统。每个@Test类都会添加测试所需的所有实体(包括 libgdx 体),并在特定的时间内运行引擎。在@After方法中,我确保删除测试添加的所有实体/实体。
@BeforeClass // executed once before all tests are performed
public static void setupWorld() {
world = new World(new Vector2(0, 0), true);
//create a pooled engine
engine = new PooledEngine();
testUtility = new TestUtility(engine, world);
// init factories
bodyFactory = BodyFactory.getInstance(world);
unitFactory = UnitFactory.getInstance(bodyFactory, engine);
battleMap = new BattleMap(sceneryFactory, engine, 123, 0); // create a battle map without any terrain or scenery
// add all the relevant systems our engine should run
engine.addSystem(new FormationSystem());
engine.addSystem(new PhysicsSystem(world));
engine.addSystem(new FollowPathSystem(battleMap));
engine.addSystem(new FollowFlowFieldSystem()); // this system works only for units!
engine.addSystem(new ArriveSystem());
engine.addSystem(new TurnTowardsSystem(engine));
engine.addSystem(new FightSystem(engine, world));}
@After
public void cleanUp() throws Exception {
// destroy all bodies in the world
testUtility.destroyObsoleteStaticBodies();
testUtility.destroyObsoleteDynamicBodies();
// remove all steerable entities
engine.removeAllEntities(Family.all(SteerableComponent.class).get());
// remove all entities that contain the static body components
engine.removeAllEntities(Family.all(BodyComponent.class).get());
engine.clearPools();
// check if world is reset correctly
assertEquals("Number of bodies in the world should be zero.", 0, world.getBodyCount());
assertEquals("Number of fixtures in the world should be zero.", 0, world.getFixtureCount());
}
这里有一个测试的例子(只是为了了解它的外观)
@Test
public void checkIfUnitTurnTowardsAttackingEnemy() {
placeUnits(new Vector2(5,5), new Vector2(5,6));
testUtility.runEngine(5, false);
// get the steerable of the enemy unit to check if it has turned around
SteerableComponent steerComp = engine.getEntitiesFor(Family.all(Enemy_Tag.class).get()).get(0).getComponent(SteerableComponent.class);
float orientationAngle = MathHelper.simplifyAngle((float)Math.toDegrees(steerComp.body.getAngle()));
assertTrue("Enemy unit that got attacked should have turned around. Offset in degrees: " + (orientationAngle-180), orientationAngle <= 180 + SteerableComponent.ANGLE_REACHED_THRESHOLD
&& orientationAngle >= 180 - SteerableComponent.ANGLE_REACHED_THRESHOLD);
assertTrue("Enemy should have angular velocity of zero.", steerComp.body.getAngularVelocity() <= SteerableComponent.ZERO_ANGULAR_SPEED_THRESHOLD);
}
我还错过了什么?顺便说一句,我正在使用 @RunWith(GdxTestRunner.class)。这是能够在测试期间访问行为树文件所必需的。
我什至尝试从 @BeforeClass 方法中删除所有代码并将所有内容放在 @Before 方法中,但这会导致同样的问题。
也许通常不建议使用 junit 测试基于 ECS 的 libgdx 游戏。任何帮助都是值得赞赏的。
答:
我在设置中发现了问题。实际上,我有两个问题在相互执行多个测试时对行为有影响。
我试图在测试后删除基于“SteerableComponent”的实体(出于清理原因),但是当实体在测试期间死亡时,该组件已被删除。
更新引擎时,请务必避免使用以下代码,因为两个测试用例之间的增量时间大于通常的增量时间,这可能会导致问题。
engine.update(Gdx.graphics.getDeltaTime());
评论