Skip to content

Commit df1d9ad

Browse files
WIP setup tests
1 parent e770f5a commit df1d9ad

File tree

6 files changed

+189
-19
lines changed

6 files changed

+189
-19
lines changed

library/build.gradle

Lines changed: 62 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ android {
1010
targetSdkVersion 29
1111
versionCode 1
1212
versionName "1.0"
13+
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
1314
}
1415
buildTypes {
1516
release {
@@ -37,8 +38,15 @@ kotlin {
3738
embedBitcode("disable")
3839
linkerOpts("-F$projectDir/../Carthage/Build/iOS")
3940
}
41+
getTest("DEBUG").linkerOpts("-F../Carthage/Build/iOS", "-framework", "GCDWebServers")
42+
// getTest("DEBUG").linkerOpts.add("-framework GCDWebServers".toString())
43+
// getTest("DEBUG").linkerOpts.add("-F../Carthage/Build/iOS".toString())
44+
// getTest("DEBUG").freeCompilerArgs.add("-framework GCDWebServers".toString())
4045
}
4146

47+
// [compilations.main, compilations.test].each {
48+
// it.cinterops {
49+
// }
4250
compilations.main.cinterops {
4351
gcdWebServer {
4452
defFile("gcdWebServer.def")
@@ -60,29 +68,64 @@ kotlin {
6068
}
6169
}
6270

63-
// posixMain {
64-
// kotlin.srcDir("src/posix/kotlin")
65-
// dependencies {
66-
// implementation group: 'org.jetbrains.kotlinx', name: 'kotlinx-coroutines-core-native', version: "1.3.4"
67-
// }
68-
// }
71+
commonTest {
72+
dependencies {
73+
implementation 'org.jetbrains.kotlin:kotlin-test-common'
74+
implementation 'org.jetbrains.kotlin:kotlin-test-annotations-common'
75+
implementation 'io.ktor:ktor-client-core:1.3.2'
76+
implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core:1.3.7'
77+
}
78+
}
6979

7080
androidMain {
71-
dependencies {
72-
implementation 'org.jetbrains.kotlin:kotlin-stdlib'
73-
implementation 'com.squareup.okhttp3:mockwebserver:4.4.0'
74-
api 'com.squareup.okio:okio:2.6.0' // needed because of actual typalias Data
75-
}
81+
dependencies {
82+
implementation 'org.jetbrains.kotlin:kotlin-stdlib'
83+
implementation 'com.squareup.okhttp3:mockwebserver:4.4.0'
84+
api 'com.squareup.okio:okio:2.6.0' // needed because of actual typalias Data
85+
}
86+
}
87+
88+
androidTest {
89+
dependencies {
90+
implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-test:1.3.7'
91+
implementation 'androidx.test.ext:junit:1.1.1'
92+
}
7693
}
7794

78-
iosMain {
79-
// kotlin.srcDirs('src/posix/kotlin')
80-
// dependsOn posixMain
95+
iosTest {
96+
dependencies {
97+
implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core-native:1.3.7'
98+
implementation 'io.ktor:ktor-client-ios:1.3.2'
99+
}
81100
}
82101

83-
// macOsMain {
84-
// kotlin.srcDirs('src/iOSMain/kotlin')
85-
//// dependsOn posixMain
86-
// }
87102
}
88-
}
103+
}
104+
105+
def testOutputFile() {
106+
return kotlin.targets["iosX64"].binaries.getTest('DEBUG').outputFile
107+
}
108+
109+
task copyGCDWebServers(type: Copy) {
110+
def testDir = testOutputFile().parentFile.absolutePath
111+
def path = "$testDir/Frameworks/GCDWebServers.framework"
112+
113+
from "$projectDir/../Carthage/Build/iOS/GCDWebServers.framework"
114+
into path
115+
}
116+
117+
task iosTest {
118+
dependsOn 'linkDebugTestIosX64'
119+
group = JavaBasePlugin.VERIFICATION_GROUP
120+
description = "Runs tests for target 'ios' on an iOS simulator"
121+
122+
doLast {
123+
def binary = testOutputFile().absolutePath
124+
exec {
125+
commandLine 'xcrun', 'simctl', 'spawn', 'booted', binary
126+
}
127+
}
128+
}
129+
130+
iosTest.dependsOn copyGCDWebServers
131+
copyGCDWebServers.mustRunAfter(linkDebugTestIosX64)
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
package dev.michallaskowski.mokttp
2+
3+
import androidx.test.ext.junit.runners.AndroidJUnit4
4+
import kotlinx.coroutines.CoroutineScope
5+
import kotlinx.coroutines.runBlocking
6+
import org.junit.Rule
7+
import org.junit.runner.RunWith
8+
9+
@RunWith(AndroidJUnit4::class)
10+
actual abstract class BaseTest {
11+
@get:Rule
12+
var coroutineTestRule = CoroutineTestRule()
13+
14+
actual fun <T> runTest(block: suspend CoroutineScope.() -> T) {
15+
runBlocking { block() }
16+
}
17+
}
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
package dev.michallaskowski.mokttp
2+
3+
import kotlinx.coroutines.Dispatchers
4+
import kotlinx.coroutines.ExecutorCoroutineDispatcher
5+
import kotlinx.coroutines.newSingleThreadContext
6+
import kotlinx.coroutines.test.resetMain
7+
import kotlinx.coroutines.test.setMain
8+
import org.junit.rules.TestWatcher
9+
import org.junit.runner.Description
10+
11+
/**
12+
* Use this rule to update the Main dispatcher ahead of tests. By delegating the main dispatcher to a new thread.
13+
* we can block the current thread and still dispatch main coroutines
14+
*/
15+
class CoroutineTestRule(
16+
private val testDispatcher: ExecutorCoroutineDispatcher = newSingleThreadContext("UI thread")
17+
) : TestWatcher() {
18+
override fun starting(description: Description?) {
19+
super.starting(description)
20+
Dispatchers.setMain(testDispatcher)
21+
}
22+
23+
override fun finished(description: Description?) {
24+
super.finished(description)
25+
Dispatchers.resetMain()
26+
}
27+
}
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
package dev.michallaskowski.mokttp
2+
3+
import kotlinx.coroutines.CoroutineScope
4+
5+
// based on https://github.com/touchlab/KaMPKit/blob/master/shared/src/commonTest/kotlin/co/touchlab/kampkit/BaseTest.kt
6+
expect abstract class BaseTest() {
7+
fun <T> runTest(block: suspend CoroutineScope.() -> T)
8+
}
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
package dev.michallaskowski.mokttp
2+
3+
import io.ktor.client.HttpClient
4+
import io.ktor.client.request.get
5+
import kotlin.test.AfterTest
6+
import kotlin.test.BeforeTest
7+
import kotlin.test.Test
8+
import kotlin.test.assertEquals
9+
10+
class HttpServerTest: BaseTest() {
11+
12+
private lateinit var server: HttpServer
13+
private lateinit var client: HttpClient
14+
15+
@BeforeTest
16+
fun setup() = runTest {
17+
server = HttpServer()
18+
client = HttpClient()
19+
}
20+
21+
@AfterTest
22+
fun teardown() = runTest {
23+
// todo: server close
24+
client.close()
25+
}
26+
27+
@Test
28+
fun someTest() = runTest {
29+
assertEquals(1, 1)
30+
}
31+
32+
@Test
33+
fun returns200OkForProperPath() = runTest {
34+
server.router = object: Router {
35+
override fun handleRequest(request: Request): Response {
36+
if (request.path != "/test") {
37+
return Response(404, emptyMap(), null, null)
38+
}
39+
return Response(200, emptyMap(), Data("test"), null)
40+
}
41+
}
42+
43+
server.start(8080)
44+
45+
val response = client.get<String>("http://localhost:8080/test")
46+
assertEquals(response, "test")
47+
}
48+
49+
}
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
package dev.michallaskowski.mokttp
2+
3+
import kotlinx.coroutines.CoroutineScope
4+
import kotlinx.coroutines.Dispatchers
5+
import kotlinx.coroutines.GlobalScope
6+
import kotlinx.coroutines.launch
7+
import platform.CoreFoundation.CFRunLoopGetCurrent
8+
import platform.CoreFoundation.CFRunLoopRun
9+
import platform.CoreFoundation.CFRunLoopStop
10+
11+
actual abstract class BaseTest {
12+
actual fun <T> runTest(block: suspend CoroutineScope.() -> T) {
13+
var error: Throwable? = null
14+
GlobalScope.launch(Dispatchers.Main) {
15+
try {
16+
block()
17+
} catch (t: Throwable) {
18+
error = t
19+
} finally {
20+
CFRunLoopStop(CFRunLoopGetCurrent())
21+
}
22+
}
23+
CFRunLoopRun()
24+
error?.also { throw it }
25+
}
26+
}

0 commit comments

Comments
 (0)