长话短说:我正在使用 libgdx/ECS(实体组件系统)开发一个小游戏,现在多次遇到我更改代码的问题,之后一些其他行为无法按预期工作(例如,单位无法不再移动到目标位置)。
为了避免将来出现此类问题,我的想法是使用 junit4 创建简单的游戏测试。设置完所有内容后,我现在遇到一个奇怪的问题:如果我单独执行测试用例,它们就会通过。当我尝试将它们一起运行时,它们就失败了。
在 @BeforeClass 方法中,我创建 libgdx“世界”,加载引擎并添加测试所需的所有系统。每个 @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());