单元测试通过无头应用程序调用着色器程序(如舞台)的 Libgdx 类



我正在尝试对我的libgdx应用程序的core包进行单元测试。

模拟ShaderProgram以便可以测试根类的最佳方法是什么?

给定 Libgdx 测试运行程序的以下初始化,

init {
    val conf = HeadlessApplicationConfiguration()
    HeadlessApplication(this, conf)
    Gdx.gl = mock(GL20::class.java) 
    Gdx.gl20 = mock(GL20::class.java)
    Gdx.gl30 = mock(GL30::class.java)
    Gdx.graphics = mock(Graphics::class.java)
    `when`(Gdx.graphics.height).thenReturn(dimensions)
    `when`(Gdx.graphics.width).thenReturn(dimensions)
}

和被测试的函数(位于Application Listener的子类中(,

override fun create() {
    ...
    stage = Stage(ScreenViewport())
    ...
}

尝试编译着色器时,Stage 内部发生错误。

即,从com.badlogic.gdx.graphics.g2d SpriteBatch.java

ShaderProgram shader = new ShaderProgram(vertexShader, fragmentShader);
if (shader.isCompiled() == false) throw new IllegalArgumentException("Error compiling shader: " + shader.getLog());

shader.isCompiled()似乎总是为HeadlessApplication返回 false。

由于到目前为止还没有答案,我想分享我目前的知识/意见:

首先,我们需要问一个问题:我们甚至可以为GUI编写单元测试吗?如果你想要一个深入的答案,看看这个问题。总而言之:您可以通过从帧缓冲区计算哈希来对 GUI 进行单元测试,但一般建议是将尽可能多的逻辑移出 GUI,并且根本不对 GUI 进行单元测试。除此之外,我和大多数运行代码的服务器都没有对OpenGL的硬件支持。假设我们不想打扰软件渲染,则无法对GUI本身进行单元测试。

基于这些信息,我认为我的逻辑与我的GUI分离得不够好。但是,当进一步研究 scene2d 和围绕它的许多教程时,很明显 scene2d 希望您通过设计将代码的逻辑和 GUI 部分结合起来,请参阅此问题以供参考。

假设你同意 scene2d 使得很难将你的逻辑和 GUI 分开的观点,我们现在面临着操作的问题,而常见的解决方案不适用。

在我看来,libGDX的所有元素都应该与HeadlessBackend完全兼容,它们不是libGDX的设计缺陷。到目前为止,我想出的唯一解决方法是在需要时模拟SpriteBatch并将其传递给舞台:

val stage = Stage(myViewport, if (isHeadless) mock(SpriteBatch::class.java) else SpriteBatch())

虽然这允许您正常使用您的舞台,但我不认为它是一个真正的解决方案,因为您需要编写代码测试感知。

最新更新