Skip to content

Commit c3148e9

Browse files
m4gr3ddsnopek
andcommitted
Add Android instrumented tests to the app module
This builds on the work from @dsnopek in https://github.com/dsnopek/javaclasswrapper-test, by importing the set of JavaClassWrapper tests from that repo within the Godot core repo in order to bootstrap and standardize how we write and run Android instrumented tests. The approach used here should serve as a base to build upon to expand the set of instrumented tests used to validate the project's stability. Co-authored-by: David Snopek <[email protected]>
1 parent 190c1e0 commit c3148e9

31 files changed

+1002
-0
lines changed

platform/android/java/app/build.gradle

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,11 @@ configurations {
3434
}
3535

3636
dependencies {
37+
// Android instrumented test dependencies
38+
androidTestImplementation "androidx.test.ext:junit:1.3.0"
39+
androidTestImplementation "androidx.test.espresso:espresso-core:3.7.0"
40+
androidTestImplementation "org.jetbrains.kotlin:kotlin-test:1.3.11"
41+
3742
implementation "androidx.fragment:fragment:$versions.fragmentVersion"
3843
implementation "androidx.core:core-splashscreen:$versions.splashscreenVersion"
3944

@@ -114,6 +119,8 @@ android {
114119
targetSdkVersion getExportTargetSdkVersion()
115120

116121
missingDimensionStrategy 'products', 'template'
122+
123+
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
117124
}
118125

119126
lintOptions {
@@ -214,10 +221,19 @@ android {
214221
flavorDimensions 'edition'
215222

216223
productFlavors {
224+
// Product flavor for the standard (no .net support) builds.
217225
standard {
218226
getIsDefault().set(true)
219227
}
228+
229+
// Product flavor for the Mono (.net) builds.
220230
mono {}
231+
232+
// Product flavor used for running instrumented tests.
233+
instrumented {
234+
applicationIdSuffix ".instrumented"
235+
versionNameSuffix "-instrumented"
236+
}
221237
}
222238

223239
sourceSets {
Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
/**************************************************************************/
2+
/* GodotAppTest.kt */
3+
/**************************************************************************/
4+
/* This file is part of: */
5+
/* GODOT ENGINE */
6+
/* https://godotengine.org */
7+
/**************************************************************************/
8+
/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
9+
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
10+
/* */
11+
/* Permission is hereby granted, free of charge, to any person obtaining */
12+
/* a copy of this software and associated documentation files (the */
13+
/* "Software"), to deal in the Software without restriction, including */
14+
/* without limitation the rights to use, copy, modify, merge, publish, */
15+
/* distribute, sublicense, and/or sell copies of the Software, and to */
16+
/* permit persons to whom the Software is furnished to do so, subject to */
17+
/* the following conditions: */
18+
/* */
19+
/* The above copyright notice and this permission notice shall be */
20+
/* included in all copies or substantial portions of the Software. */
21+
/* */
22+
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
23+
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
24+
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
25+
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
26+
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
27+
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
28+
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
29+
/**************************************************************************/
30+
31+
package com.godot.game
32+
33+
import android.util.Log
34+
import androidx.test.ext.junit.rules.ActivityScenarioRule
35+
import androidx.test.ext.junit.runners.AndroidJUnit4
36+
import com.godot.game.test.GodotAppInstrumentedTestPlugin
37+
import org.godotengine.godot.plugin.GodotPluginRegistry
38+
import org.junit.Rule
39+
import org.junit.Test
40+
import org.junit.runner.RunWith
41+
import kotlin.test.assertNotNull
42+
import kotlin.test.assertTrue
43+
44+
/**
45+
* This instrumented test will launch the `instrumented` version of GodotApp and run a set of tests against it.
46+
*/
47+
@RunWith(AndroidJUnit4::class)
48+
class GodotAppTest {
49+
50+
companion object {
51+
private val TAG = GodotAppTest::class.java.simpleName
52+
}
53+
54+
@get:Rule
55+
val godotAppRule = ActivityScenarioRule(GodotApp::class.java)
56+
57+
/**
58+
* Runs the JavaClassWrapper tests via the GodotAppInstrumentedTestPlugin.
59+
*/
60+
@Test
61+
fun runJavaClassWrapperTests() {
62+
val testPlugin = GodotPluginRegistry.getPluginRegistry()
63+
.getPlugin("GodotAppInstrumentedTestPlugin") as GodotAppInstrumentedTestPlugin?
64+
assertNotNull(testPlugin)
65+
66+
Log.d(TAG, "Waiting for the Godot main loop to start..")
67+
testPlugin.waitForGodotMainLoopStarted()
68+
69+
Log.d(TAG, "Running JavaClassWrapper tests..")
70+
val result = testPlugin.runJavaClassWrapperTests()
71+
assertNotNull(result)
72+
result.exceptionOrNull()?.let { throw it }
73+
assertTrue(result.isSuccess)
74+
}
75+
}
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
2+
3+
<application>
4+
<meta-data
5+
android:name="org.godotengine.plugin.v2.GodotAppInstrumentedTestPlugin"
6+
android:value="com.godot.game.test.GodotAppInstrumentedTestPlugin"/>
7+
</application>
8+
9+
</manifest>
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
# Normalize EOL for all files that Git considers text files.
2+
* text=auto eol=lf
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
# Godot 4+ specific ignores
2+
/android/
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
[docks]
2+
3+
dock_3_selected_tab_idx=0
4+
dock_4_selected_tab_idx=0
5+
dock_floating={}
6+
dock_filesystem_h_split_offset=480
7+
dock_filesystem_v_split_offset=0
8+
dock_filesystem_display_mode=2
9+
dock_filesystem_file_sort=0
10+
dock_filesystem_file_list_display_mode=0
11+
dock_filesystem_selected_paths=PackedStringArray("res://")
12+
dock_filesystem_uncollapsed_paths=PackedStringArray("Favorites")
13+
dock_node_current_tab=0
14+
dock_history_include_scene=true
15+
dock_history_include_global=true
16+
dock_bottom=["FileSystem"]
17+
dock_closed=[]
18+
dock_split_2=0
19+
dock_hsplit_1=0
20+
dock_hsplit_2=270
21+
dock_hsplit_3=-270
22+
dock_hsplit_4=0
23+
dock_3="Scene,Import,History"
24+
dock_4="Inspector,Node,FileSystem"
25+
26+
[EditorNode]
27+
28+
open_scenes=PackedStringArray("res://main.tscn")
29+
current_scene="res://main.tscn"
30+
center_split_offset=0
31+
selected_default_debugger_tab_idx=0
32+
selected_main_editor_idx=0
33+
34+
[EditorWindow]
35+
36+
screen=0
37+
mode="maximized"
38+
position=Vector2i(0, 76)
39+
40+
[ScriptEditor]
41+
42+
open_scripts=[]
43+
selected_script=""
44+
open_help=[]
45+
script_split_offset=400
46+
list_split_offset=0
47+
zoom_factor=1.0
48+
49+
[GameView]
50+
51+
floating_window_rect=Rect2i(0, 0, 0, 0)
52+
floating_window_screen=-1
53+
54+
[ShaderEditor]
55+
56+
open_shaders=[]
57+
split_offset=400
58+
selected_shader=""
59+
text_shader_zoom_factor=1.0
625 Bytes
Binary file not shown.
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
[folding]
2+
3+
sections_unfolded=PackedStringArray()
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
72322a848ab928aa5c89f0cb78209805
2+
::res://::1758527796
3+
icon.svg::CompressedTexture2D::1299313878201654985::1757045723::1758527796::1::::<><><>0<>0<>479f8a36ed4d9c512842e5f33fa0a959<>res://.godot/imported/icon.svg-218a8f2b3041327d8a5756f3a245f83b.ctex::
4+
main.gd::GDScript::3925896905396205184::1758519166::0::1::::<>Node2D<><>0<>0<><>::
5+
main.tscn::PackedScene::5252245462687868703::1758519070::0::1::::<><><>0<>0<><>::uid://7rn4g3gs3yse::::res://main.gd

0 commit comments

Comments
 (0)