mirror of
https://github.com/yairm210/Unciv.git
synced 2025-07-06 00:09:23 +07:00
Clean up console output of unit test runs (#11134)
* Allow tests to discard console output selectively, by default collect and discard unless result is failure * Fix debug change and a little source clarification
This commit is contained in:
@ -17,7 +17,6 @@ import com.unciv.models.translations.squareBraceRegex
|
|||||||
import com.unciv.models.translations.tr
|
import com.unciv.models.translations.tr
|
||||||
import com.unciv.testing.GdxTestRunner
|
import com.unciv.testing.GdxTestRunner
|
||||||
import com.unciv.utils.Log
|
import com.unciv.utils.Log
|
||||||
import com.unciv.utils.debug
|
|
||||||
import org.junit.Assert
|
import org.junit.Assert
|
||||||
import org.junit.Before
|
import org.junit.Before
|
||||||
import org.junit.Test
|
import org.junit.Test
|
||||||
@ -84,7 +83,8 @@ class TranslationTests {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun translationsFromJSONsCanBeGenerated() {
|
fun translationsFromJSONsCanBeGenerated() {
|
||||||
// it triggers generation of the translation's strings
|
// Triggers generation of the translation's strings
|
||||||
|
// Will output "Translation writer took...", which is suppressed unless you use the @RedirectOutput(RedirectPolicy.Show) annotation
|
||||||
val stringsSize = TranslationFileWriter.getGeneratedStringsSize()
|
val stringsSize = TranslationFileWriter.getGeneratedStringsSize()
|
||||||
|
|
||||||
Assert.assertTrue("This test will only pass when all .json files are serializable",
|
Assert.assertTrue("This test will only pass when all .json files are serializable",
|
||||||
@ -308,7 +308,6 @@ class TranslationTests {
|
|||||||
addTranslation("best friend", "closest ally")
|
addTranslation("best friend", "closest ally")
|
||||||
addTranslation("America", "The old British colonies")
|
addTranslation("America", "The old British colonies")
|
||||||
|
|
||||||
debug("[Dad] and [my [best friend]]".getPlaceholderText())
|
|
||||||
Assert.assertEquals(listOf("Dad","my [best friend]"),
|
Assert.assertEquals(listOf("Dad","my [best friend]"),
|
||||||
"[Dad] and [my [best friend]]".getPlaceholderParameters())
|
"[Dad] and [my [best friend]]".getPlaceholderParameters())
|
||||||
Assert.assertEquals("Father and indeed mine own closest ally", "[Dad] and [my [best friend]]".tr())
|
Assert.assertEquals("Father and indeed mine own closest ally", "[Dad] and [my [best friend]]".tr())
|
||||||
|
@ -1,103 +0,0 @@
|
|||||||
/*******************************************************************************
|
|
||||||
* Copyright 2015 See AUTHORS file.
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
******************************************************************************/
|
|
||||||
|
|
||||||
package com.unciv.testing;
|
|
||||||
|
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
import com.badlogic.gdx.ApplicationListener;
|
|
||||||
import com.badlogic.gdx.Gdx;
|
|
||||||
import com.badlogic.gdx.backends.headless.HeadlessApplication;
|
|
||||||
import com.badlogic.gdx.backends.headless.HeadlessApplicationConfiguration;
|
|
||||||
import com.badlogic.gdx.graphics.GL20;
|
|
||||||
import org.junit.runner.notification.RunNotifier;
|
|
||||||
import org.junit.runners.BlockJUnit4ClassRunner;
|
|
||||||
import org.junit.runners.model.FrameworkMethod;
|
|
||||||
import org.junit.runners.model.InitializationError;
|
|
||||||
|
|
||||||
import static org.mockito.Mockito.*;
|
|
||||||
|
|
||||||
public class GdxTestRunner extends BlockJUnit4ClassRunner implements ApplicationListener {
|
|
||||||
|
|
||||||
private final Map<FrameworkMethod, RunNotifier> invokeInRender = new HashMap<>();
|
|
||||||
|
|
||||||
public GdxTestRunner(Class<?> klass) throws InitializationError {
|
|
||||||
super(klass);
|
|
||||||
HeadlessApplicationConfiguration conf = new HeadlessApplicationConfiguration();
|
|
||||||
|
|
||||||
new HeadlessApplication(this, conf);
|
|
||||||
Gdx.gl = mock(GL20.class);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void create() {
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void resume() {
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void render() {
|
|
||||||
synchronized (invokeInRender) {
|
|
||||||
for (Map.Entry<FrameworkMethod, RunNotifier> each : invokeInRender.entrySet()) {
|
|
||||||
super.runChild(each.getKey(), each.getValue());
|
|
||||||
}
|
|
||||||
invokeInRender.clear();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void resize(int width, int height) {
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void pause() {
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void dispose() {
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void runChild(FrameworkMethod method, RunNotifier notifier) {
|
|
||||||
synchronized (invokeInRender) {
|
|
||||||
// add for invoking in render phase, where gl context is available
|
|
||||||
invokeInRender.put(method, notifier);
|
|
||||||
}
|
|
||||||
// wait until that test was invoked
|
|
||||||
waitUntilInvokedInRenderMethod();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
private void waitUntilInvokedInRenderMethod() {
|
|
||||||
try {
|
|
||||||
while (true) {
|
|
||||||
Thread.sleep(10);
|
|
||||||
synchronized (invokeInRender) {
|
|
||||||
if (invokeInRender.isEmpty())
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} catch (InterruptedException e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
126
tests/src/com/unciv/testing/GdxTestRunner.kt
Normal file
126
tests/src/com/unciv/testing/GdxTestRunner.kt
Normal file
@ -0,0 +1,126 @@
|
|||||||
|
/*******************************************************************************
|
||||||
|
* Copyright 2015 See AUTHORS file.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
******************************************************************************/
|
||||||
|
|
||||||
|
package com.unciv.testing
|
||||||
|
|
||||||
|
import com.badlogic.gdx.ApplicationListener
|
||||||
|
import com.badlogic.gdx.Gdx
|
||||||
|
import com.badlogic.gdx.backends.headless.HeadlessApplication
|
||||||
|
import com.badlogic.gdx.backends.headless.HeadlessApplicationConfiguration
|
||||||
|
import com.badlogic.gdx.graphics.GL20
|
||||||
|
import org.junit.runner.notification.Failure
|
||||||
|
import org.junit.runner.notification.RunListener
|
||||||
|
import org.junit.runner.notification.RunNotifier
|
||||||
|
import org.junit.runners.BlockJUnit4ClassRunner
|
||||||
|
import org.junit.runners.model.FrameworkMethod
|
||||||
|
import org.mockito.Mockito
|
||||||
|
import java.io.ByteArrayOutputStream
|
||||||
|
import java.io.OutputStream
|
||||||
|
import java.io.PrintStream
|
||||||
|
|
||||||
|
|
||||||
|
class GdxTestRunner(klass: Class<*>?) : BlockJUnit4ClassRunner(klass), ApplicationListener {
|
||||||
|
private val invokeInRender: MutableMap<FrameworkMethod, RunNotifier> = HashMap()
|
||||||
|
|
||||||
|
init {
|
||||||
|
val conf = HeadlessApplicationConfiguration()
|
||||||
|
HeadlessApplication(this, conf)
|
||||||
|
Gdx.gl = Mockito.mock(GL20::class.java)
|
||||||
|
}
|
||||||
|
|
||||||
|
// ApplicationListener interface
|
||||||
|
override fun create() {}
|
||||||
|
override fun resume() {}
|
||||||
|
override fun resize(width: Int, height: Int) {}
|
||||||
|
override fun pause() {}
|
||||||
|
override fun dispose() {}
|
||||||
|
|
||||||
|
override fun render() {
|
||||||
|
synchronized(invokeInRender) {
|
||||||
|
for ((method, notifier) in invokeInRender) {
|
||||||
|
val redirect = method.getAnnotation(RedirectOutput::class.java)
|
||||||
|
?.policy
|
||||||
|
?: RedirectPolicy.ShowOnFailure
|
||||||
|
when (redirect) {
|
||||||
|
RedirectPolicy.ShowOnFailure ->
|
||||||
|
runChildRedirectingOutput(method, notifier)
|
||||||
|
RedirectPolicy.Discard ->
|
||||||
|
runChildDiscardingOutput(method, notifier)
|
||||||
|
else ->
|
||||||
|
super.runChild(method, notifier)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
invokeInRender.clear()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// BlockJUnit4ClassRunner interface
|
||||||
|
override fun runChild(method: FrameworkMethod, notifier: RunNotifier) {
|
||||||
|
synchronized(invokeInRender) {
|
||||||
|
// add for invoking in render phase, where gl context is available
|
||||||
|
invokeInRender.put(method, notifier)
|
||||||
|
}
|
||||||
|
// wait until that test was invoked
|
||||||
|
waitUntilInvokedInRenderMethod()
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun waitUntilInvokedInRenderMethod() {
|
||||||
|
try {
|
||||||
|
while (true) {
|
||||||
|
Thread.sleep(10)
|
||||||
|
if (synchronized(invokeInRender) { invokeInRender.isEmpty() })
|
||||||
|
break
|
||||||
|
}
|
||||||
|
} catch (e: InterruptedException) {
|
||||||
|
e.printStackTrace()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Standard output redirection
|
||||||
|
private fun runChildRedirectingOutput(method: FrameworkMethod, notifier: RunNotifier) {
|
||||||
|
val outputBuffer = ByteArrayOutputStream(2048)
|
||||||
|
val outputStream = PrintStream(outputBuffer)
|
||||||
|
val oldOutputStream = System.out
|
||||||
|
val listener = object : RunListener() {
|
||||||
|
override fun testFailure(failure: Failure?) {
|
||||||
|
outputBuffer.writeTo(oldOutputStream)
|
||||||
|
super.testFailure(failure)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
System.setOut(outputStream)
|
||||||
|
notifier.addListener(listener)
|
||||||
|
try {
|
||||||
|
super.runChild(method, notifier)
|
||||||
|
} finally {
|
||||||
|
outputStream.close()
|
||||||
|
System.setOut(oldOutputStream)
|
||||||
|
notifier.removeListener(listener)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun runChildDiscardingOutput(method: FrameworkMethod, notifier: RunNotifier) {
|
||||||
|
val oldOutputStream = System.out
|
||||||
|
System.setOut(PrintStream(object : OutputStream() {
|
||||||
|
override fun write(codepoint: Int) {}
|
||||||
|
}))
|
||||||
|
try {
|
||||||
|
super.runChild(method, notifier)
|
||||||
|
} finally {
|
||||||
|
System.setOut(oldOutputStream)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
15
tests/src/com/unciv/testing/RedirectOutput.kt
Normal file
15
tests/src/com/unciv/testing/RedirectOutput.kt
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
package com.unciv.testing
|
||||||
|
|
||||||
|
enum class RedirectPolicy { Show, ShowOnFailure, Discard }
|
||||||
|
|
||||||
|
@Retention(AnnotationRetention.RUNTIME)
|
||||||
|
@Target(AnnotationTarget.FUNCTION)
|
||||||
|
/**
|
||||||
|
* This annotation controls the [GdxTestRunner] feature to redirect and discard console output from tests.
|
||||||
|
*
|
||||||
|
* Settings:
|
||||||
|
* * [RedirectPolicy.Discard]: Output is discarded.
|
||||||
|
* * [RedirectPolicy.ShowOnFailure] (**default**): Collected output is written to the console only when the test fails).
|
||||||
|
* * [RedirectPolicy.Show]: Do not redirect, show console output immediately.
|
||||||
|
*/
|
||||||
|
annotation class RedirectOutput(val policy: RedirectPolicy)
|
Reference in New Issue
Block a user