mirror of
https://github.com/yairm210/Unciv.git
synced 2025-07-04 23:40:01 +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.testing.GdxTestRunner
|
||||
import com.unciv.utils.Log
|
||||
import com.unciv.utils.debug
|
||||
import org.junit.Assert
|
||||
import org.junit.Before
|
||||
import org.junit.Test
|
||||
@ -84,7 +83,8 @@ class TranslationTests {
|
||||
|
||||
@Test
|
||||
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()
|
||||
|
||||
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("America", "The old British colonies")
|
||||
|
||||
debug("[Dad] and [my [best friend]]".getPlaceholderText())
|
||||
Assert.assertEquals(listOf("Dad","my [best friend]"),
|
||||
"[Dad] and [my [best friend]]".getPlaceholderParameters())
|
||||
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