Skip to content

Commit bbb77b9

Browse files
committed
Refine Proxy (#13)
* Refine Proxy * fix bug
1 parent b41e72c commit bbb77b9

File tree

11 files changed

+90
-112
lines changed

11 files changed

+90
-112
lines changed

examples/simple-api-test/src/test/kotlin/Steps.kt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import com.example.demoapp.App
22
import com.github.tomakehurst.wiremock.WireMockServer
33
import com.thoughtworks.gauge.AfterSuite
44
import com.thoughtworks.gauge.BeforeSuite
5-
import com.uzabase.playtest2.core.config.Configuration
5+
import com.uzabase.playtest2.core.config.Configuration.Companion.playtest2
66
import com.uzabase.playtest2.core.config.plus
77
import com.uzabase.playtest2.http.config.http
88
import com.uzabase.playtest2.wiremock.config.wireMock
@@ -13,7 +13,7 @@ class Steps {
1313

1414
@BeforeSuite
1515
fun beforeSuite() {
16-
Configuration.playtest2 {
16+
playtest2 {
1717
http(URI("http://localhost:8080").toURL()) +
1818
wireMock("InnerAPI", URI("http://localhost:3000").toURL())
1919
}
Lines changed: 20 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -1,61 +1,31 @@
11
package com.uzabase.playtest2.core.proxy
22

33
import com.uzabase.playtest2.core.assertion.Assertable
4-
import com.uzabase.playtest2.core.assertion.PlaytestException
5-
import com.uzabase.playtest2.core.assertion.playtestException
6-
import com.uzabase.playtest2.core.zoom.Zoomable
7-
import java.lang.reflect.Proxy
84

9-
data class AssertableProxyFunctions<T>(
10-
val asString: (T) -> String = { throw PlaytestException("Cannot convert $it to String") },
11-
val asLong: (T) -> Long = { throw PlaytestException("Cannot convert $it to Long") },
12-
val asBoolean: (T) -> Boolean = { throw PlaytestException("Cannot convert $it to Boolean") },
13-
val asRaw: (T) -> Any = { it as Any }
14-
)
15-
16-
fun <K> unzoomable(): Zoomable<K> = object : Zoomable<K> {
17-
override fun zoom(key: K): Any {
18-
throw UnsupportedOperationException("Cannot zoom")
19-
}
20-
21-
}
22-
23-
@Suppress("UNCHECKED_CAST")
245
class ProxyFactory {
256
companion object {
26-
inline fun <reified A, K> make(
27-
obj: A,
28-
fns: AssertableProxyFunctions<A>,
29-
zoomable: Zoomable<K> = unzoomable()
30-
): Any =
31-
Proxy.newProxyInstance(
32-
Assertable::class.java.classLoader,
33-
arrayOf(
34-
Assertable::class.java,
35-
Zoomable::class.java
36-
)
37-
) { _, method, args ->
38-
when (method.name) {
39-
"asString" -> fns.asString(obj)
40-
"asLong" -> fns.asLong(obj)
41-
"asBoolean" -> fns.asBoolean(obj)
42-
"asRaw" -> fns.asRaw(obj)
43-
"zoom" -> zoomable.zoom(args[0] as K)
44-
else -> playtestException("Cannot execute this method")
45-
}
7+
fun ofString(s: String): Assertable =
8+
object : Assertable {
9+
override fun asLong(): Long = s.toLong()
10+
override fun asString(): String = s
11+
override fun asBoolean(): Boolean = s.toBoolean()
12+
override fun asRaw(): Any = s
4613
}
4714

48-
fun fromStringValue(s: String): Any = make<String, Unit>(s, AssertableProxyFunctions(
49-
asString = { s },
50-
asBoolean = { s.toBoolean() }
51-
))
52-
53-
fun fromLongValue(l: Long): Any = make<Long, Unit>(l, AssertableProxyFunctions(
54-
asLong = { l }
55-
))
15+
fun ofLong(l: Long): Assertable =
16+
object : Assertable {
17+
override fun asLong(): Long = l
18+
override fun asString(): String = l.toString()
19+
override fun asBoolean(): Boolean = throw UnsupportedOperationException()
20+
override fun asRaw(): Any = l
21+
}
5622

57-
fun fromBooleanValue(b: Boolean) = make<Boolean, Unit>(b, AssertableProxyFunctions(
58-
asBoolean = { b }
59-
))
23+
fun ofBoolean(b: Boolean): Assertable =
24+
object : Assertable {
25+
override fun asLong(): Long = throw UnsupportedOperationException()
26+
override fun asString(): String = b.toString()
27+
override fun asBoolean(): Boolean = b
28+
override fun asRaw(): Any = b
29+
}
6030
}
6131
}

playtest-core/src/test/kotlin/com/uzabase/playtest2/core/AssertionStepsTest.kt

Lines changed: 19 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,26 @@
11
package com.uzabase.playtest2.core
22

33
import com.thoughtworks.gauge.datastore.ScenarioDataStore
4+
import com.uzabase.playtest2.core.assertion.Assertable
45
import com.uzabase.playtest2.core.assertion.PlaytestException
5-
import com.uzabase.playtest2.core.proxy.AssertableProxyFunctions
66
import com.uzabase.playtest2.core.proxy.ProxyFactory
77
import io.kotest.assertions.throwables.shouldThrow
88
import io.kotest.core.spec.style.FunSpec
99
import io.kotest.matchers.shouldBe
1010

1111
data class FullName(val firstName: String, val lastName: String)
1212

13-
val FromFullName = { fullName: FullName ->
14-
ProxyFactory.make<FullName, Unit>(fullName, AssertableProxyFunctions(
15-
asString = { "${it.firstName} ${it.lastName} :)" }
16-
))
13+
private val FromFullName = { fullName: FullName ->
14+
object : Assertable {
15+
override fun asLong(): Long = throw UnsupportedOperationException()
16+
17+
override fun asString(): String = "${fullName.firstName} ${fullName.lastName} :)"
18+
19+
override fun asBoolean(): Boolean = false
20+
21+
override fun asRaw(): Any = throw UnsupportedOperationException()
22+
23+
}
1724
}
1825

1926
class AssertionStepsTest : FunSpec({
@@ -25,27 +32,27 @@ class AssertionStepsTest : FunSpec({
2532
context("Assertions") {
2633
context("happy path") {
2734
test("long value") {
28-
ScenarioDataStore.put(K.AssertionTarget, ProxyFactory.fromLongValue(200L))
35+
ScenarioDataStore.put(K.AssertionTarget, ProxyFactory.ofLong(200L))
2936
sut.shouldBeLongValue(200L)
3037
}
3138

3239
test("string value") {
33-
ScenarioDataStore.put(K.AssertionTarget, ProxyFactory.fromStringValue("Hello, world"))
40+
ScenarioDataStore.put(K.AssertionTarget, ProxyFactory.ofString("Hello, world"))
3441
sut.shouldBeStringValue("Hello, world")
3542
}
3643

3744
test("strict bool value") {
38-
ScenarioDataStore.put(K.AssertionTarget, ProxyFactory.fromBooleanValue(true))
45+
ScenarioDataStore.put(K.AssertionTarget, ProxyFactory.ofBoolean(true))
3946
sut.shouldBeBoolean()
4047
}
4148

4249
test("strict true") {
43-
ScenarioDataStore.put(K.AssertionTarget, ProxyFactory.fromBooleanValue(true))
50+
ScenarioDataStore.put(K.AssertionTarget, ProxyFactory.ofBoolean(true))
4451
sut.shouldBeTrue()
4552
}
4653

4754
test("strict false") {
48-
ScenarioDataStore.put(K.AssertionTarget, ProxyFactory.fromBooleanValue(false))
55+
ScenarioDataStore.put(K.AssertionTarget, ProxyFactory.ofBoolean(false))
4956
sut.shouldBeFalse()
5057
}
5158
}
@@ -84,12 +91,12 @@ class AssertionStepsTest : FunSpec({
8491

8592
context("contains") {
8693
test("should contains") {
87-
ScenarioDataStore.put(K.AssertionTarget, ProxyFactory.fromStringValue("Hello, world"))
94+
ScenarioDataStore.put(K.AssertionTarget, ProxyFactory.ofString("Hello, world"))
8895
sut.shouldBeContainsStringValue("world")
8996
}
9097

9198
test("should not contains") {
92-
ScenarioDataStore.put(K.AssertionTarget, ProxyFactory.fromStringValue("Hello, world"))
99+
ScenarioDataStore.put(K.AssertionTarget, ProxyFactory.ofString("Hello, world"))
93100
shouldThrow<PlaytestException> {
94101
sut.shouldBeContainsStringValue("John")
95102
}.message.shouldBe("should contains John")

playtest-core/src/test/kotlin/com/uzabase/playtest2/core/config/ConfigurationTest.kt

Lines changed: 0 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,5 @@
11
package com.uzabase.playtest2.core.config
22

3-
import com.uzabase.playtest2.core.proxy.ProxyFactory
4-
import com.uzabase.playtest2.core.proxy.AssertableProxyFunctions
53
import io.kotest.core.spec.style.FunSpec
64
import io.kotest.data.forAll
75
import io.kotest.data.row
@@ -25,15 +23,6 @@ data class MyMod2Configuration(
2523

2624
data class Dog(val name: String, val age: Int)
2725

28-
val FromDog = { it: Dog ->
29-
ProxyFactory.make<Dog, Unit>(
30-
it,
31-
AssertableProxyFunctions(
32-
asString = { "My dog name is ${it.name}, age is ${it.age}!!" },
33-
)
34-
)
35-
}
36-
3726
fun myMod1(endpoint: URL): ConfigurationEntry =
3827
ConfigurationEntry(MyMod1ModuleKey, MyMod1Configuration(endpoint))
3928

playtest-http/src/main/kotlin/com/uzabase/playtest2/http/FocusResponseSteps.kt

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ package com.uzabase.playtest2.http
33
import com.thoughtworks.gauge.Step
44
import com.thoughtworks.gauge.datastore.ScenarioDataStore
55
import com.uzabase.playtest2.core.proxy.ProxyFactory
6-
import com.uzabase.playtest2.http.proxy.toProxy
6+
import com.uzabase.playtest2.http.proxy.HttpHeadersProxy
77
import java.net.http.HttpResponse
88
import com.uzabase.playtest2.core.K as coreK
99
import com.uzabase.playtest2.http.internal.K as intK
@@ -12,7 +12,7 @@ class FocusResponseSteps {
1212
@Step("レスポンスのステータスコードが")
1313
fun statusCode() {
1414
(ScenarioDataStore.get(intK.RESPONSE) as HttpResponse<*>)
15-
.let { ProxyFactory.fromLongValue(it.statusCode().toLong()) }
15+
.let { ProxyFactory.ofLong(it.statusCode().toLong()) }
1616
.let { ScenarioDataStore.put(coreK.AssertionTarget, it) }
1717
}
1818

@@ -25,6 +25,6 @@ class FocusResponseSteps {
2525
@Step("レスポンスのヘッダーが", "レスポンスのヘッダーの")
2626
fun headers() {
2727
(ScenarioDataStore.get(intK.RESPONSE) as HttpResponse<*>)
28-
.let { ScenarioDataStore.put(coreK.AssertionTarget, it.headers().toProxy()) }
28+
.let { ScenarioDataStore.put(coreK.AssertionTarget, it.headers().let(HttpHeadersProxy::of)) }
2929
}
3030
}
Lines changed: 2 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,15 @@
11
package com.uzabase.playtest2.http
22

3-
import com.jayway.jsonpath.JsonPath
43
import com.thoughtworks.gauge.Step
54
import com.thoughtworks.gauge.datastore.ScenarioDataStore
65
import com.uzabase.playtest2.core.K
76
import com.uzabase.playtest2.core.ScenarioDataStoreExt.ensureGet
8-
import com.uzabase.playtest2.core.proxy.AssertableProxyFunctions
9-
import com.uzabase.playtest2.core.proxy.ProxyFactory
7+
import com.uzabase.playtest2.http.proxy.JsonPathProxy
108

119
class ZoomJsonSteps {
1210
@Step("JSONのパス<jsonPath>に対応する値が")
1311
fun zoomJson(jsonPath: String): Any =
1412
ensureGet<String>(K.AssertionTarget)
15-
.let { JsonPath.read<Any>(it, jsonPath) }
16-
.let { value ->
17-
ProxyFactory.make<Any, Unit>(value, AssertableProxyFunctions(
18-
asString = { value as String },
19-
asLong = { value as Long },
20-
asBoolean = { value as Boolean },
21-
asRaw = { value }
22-
))
23-
}
13+
.let { JsonPathProxy.of(it, jsonPath) }
2414
.let { ScenarioDataStore.put(K.AssertionTarget, it) }
2515
}

playtest-http/src/main/kotlin/com/uzabase/playtest2/http/ZoomResponseHeadersSteps.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,6 @@ class ZoomResponseHeadersSteps {
1212
fun zoomMap(key: String): Any =
1313
ScenarioDataStoreExt.ensureGet<Zoomable<String>>(K.AssertionTarget)
1414
.zoom(key)
15-
?.let { ScenarioDataStore.put(K.AssertionTarget, ProxyFactory.fromStringValue(it as String)) }
15+
?.let { ScenarioDataStore.put(K.AssertionTarget, ProxyFactory.ofString(it as String)) }
1616
?: ScenarioDataStore.remove(K.AssertionTarget)
1717
}
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
package com.uzabase.playtest2.http.proxy
2+
3+
import com.jayway.jsonpath.JsonPath
4+
import com.uzabase.playtest2.core.assertion.Assertable
5+
6+
class JsonPathProxy private constructor(val json: String, val path: String) : Assertable {
7+
companion object {
8+
fun of(json: String, path: String): JsonPathProxy {
9+
return JsonPathProxy(json, path)
10+
}
11+
}
12+
13+
override fun asLong(): Long = JsonPath.read(json, path)
14+
15+
override fun asString(): String = JsonPath.read(json, path)
16+
17+
override fun asBoolean(): Boolean = JsonPath.read(json, path)
18+
19+
override fun asRaw(): Any = JsonPath.read(json, path)
20+
21+
}
Lines changed: 18 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,24 @@
11
package com.uzabase.playtest2.http.proxy
22

3-
import com.uzabase.playtest2.core.proxy.AssertableProxyFunctions
4-
import com.uzabase.playtest2.core.proxy.ProxyFactory
3+
import com.uzabase.playtest2.core.assertion.Assertable
54
import com.uzabase.playtest2.core.zoom.Zoomable
65
import java.net.http.HttpHeaders
76

8-
9-
fun HttpHeaders.toProxy(): Any =
10-
this.let { headers: HttpHeaders ->
11-
ProxyFactory.make<HttpHeaders, String>(
12-
headers,
13-
AssertableProxyFunctions(
14-
asString = {
15-
headers.map().entries.sortedBy { (k, _) -> k }
16-
.joinToString(System.lineSeparator()) { (k, v) -> "$k: ${v.joinToString(",")}" }
17-
}
18-
),
19-
zoomable = object : Zoomable<String> {
20-
override fun zoom(key: String): Any? = headers.map()[key]?.joinToString(",")
21-
}
22-
)
7+
class HttpHeadersProxy private constructor(val headers: HttpHeaders) : Assertable, Zoomable<String> {
8+
companion object {
9+
fun of(headers: HttpHeaders): HttpHeadersProxy {
10+
return HttpHeadersProxy(headers)
11+
}
2312
}
13+
14+
override fun asString(): String =
15+
headers.map().entries.sortedBy { (k, _) -> k }
16+
.joinToString(System.lineSeparator()) { (k, v) -> "$k: ${v.joinToString(",")}" }
17+
18+
override fun asRaw(): HttpHeaders = headers
19+
20+
override fun asLong(): Long = throw UnsupportedOperationException("Cannot convert to Long")
21+
override fun asBoolean(): Boolean = throw UnsupportedOperationException("Cannot convert to Boolean")
22+
23+
override fun zoom(key: String): Any? = headers.map()[key]?.joinToString(",")
24+
}

playtest-http/src/test/kotlin/com/uzabase/playtest2/http/ZoomResponseHeadersStepsTest.kt

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ package com.uzabase.playtest2.http
33
import com.thoughtworks.gauge.datastore.ScenarioDataStore
44
import com.uzabase.playtest2.core.K
55
import com.uzabase.playtest2.core.assertion.Assertable
6-
import com.uzabase.playtest2.http.proxy.toProxy
6+
import com.uzabase.playtest2.http.proxy.HttpHeadersProxy
77
import io.kotest.core.spec.style.FunSpec
88
import io.kotest.matchers.nulls.shouldBeNull
99
import io.kotest.matchers.shouldBe
@@ -18,7 +18,7 @@ class ZoomResponseHeadersStepsTest : FunSpec({
1818
test("should be zoomed") {
1919
ScenarioDataStore.put(
2020
K.AssertionTarget,
21-
HttpHeaders.of(mapOf("any-header" to listOf("any")), { _, _ -> true }).toProxy()
21+
HttpHeaders.of(mapOf("any-header" to listOf("any"))) { _, _ -> true }.let(HttpHeadersProxy::of)
2222
)
2323
sut.zoomMap("any-header")
2424
ScenarioDataStore.get(K.AssertionTarget)
@@ -29,7 +29,7 @@ class ZoomResponseHeadersStepsTest : FunSpec({
2929
test("should be removed if key is not found") {
3030
ScenarioDataStore.put(
3131
K.AssertionTarget,
32-
HttpHeaders.of(mapOf("any-header" to listOf("any")), { _, _ -> true }).toProxy()
32+
HttpHeaders.of(mapOf("any-header" to listOf("any"))) { _, _ -> true }.let(HttpHeadersProxy::of)
3333
)
3434
sut.zoomMap("not-found")
3535
ScenarioDataStore.get(K.AssertionTarget).shouldBeNull()

0 commit comments

Comments
 (0)