Skip to content

Commit 891af47

Browse files
authored
Use local httpbin to run tests (#175)
Fix #132 Start a local httpbin container to run tests against. Https requests are still using remote one since it's hard to setup local secure ssl. The requests using https are simple and during my tests I haven't seen any timeout.
1 parent beb5d26 commit 891af47

File tree

4 files changed

+75
-51
lines changed

4 files changed

+75
-51
lines changed

build.sc

+2-1
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,8 @@ trait RequestsModule extends CrossScalaModule with PublishModule with Mima {
4040
object test extends ScalaTests with TestModule.Utest {
4141
def ivyDeps = Agg(
4242
ivy"com.lihaoyi::utest::0.7.10",
43-
ivy"com.lihaoyi::ujson::1.3.13"
43+
ivy"com.lihaoyi::ujson::1.3.13",
44+
ivy"com.dimafeng::testcontainers-scala-core:0.41.3"
4445
)
4546
}
4647
}

requests/test/src-2/requests/Scala2RequestTests.scala

+5-5
Original file line numberDiff line numberDiff line change
@@ -3,15 +3,15 @@ package requests
33
import utest._
44
import ujson._
55

6-
object Scala2RequestTests extends TestSuite{
6+
object Scala2RequestTests extends HttpbinTestSuite {
77
val tests = Tests{
88

99
test("params"){
1010

1111
test("post"){
1212
for(chunkedUpload <- Seq(true, false)) {
1313
val res1 = requests.post(
14-
"https://httpbin.org/post",
14+
s"http://$localHttpbin/post",
1515
data = Map("hello" -> "world", "foo" -> "baz"),
1616
chunkedUpload = chunkedUpload
1717
).text()
@@ -22,7 +22,7 @@ object Scala2RequestTests extends TestSuite{
2222
test("put") {
2323
for (chunkedUpload <- Seq(true, false)) {
2424
val res1 = requests.put(
25-
"https://httpbin.org/put",
25+
s"http://$localHttpbin/put",
2626
data = Map("hello" -> "world", "foo" -> "baz"),
2727
chunkedUpload = chunkedUpload
2828
).text()
@@ -31,10 +31,10 @@ object Scala2RequestTests extends TestSuite{
3131
}
3232

3333
test("send"){
34-
requests.send("get")("https://httpbin.org/get?hello=world&foo=baz")
34+
requests.send("get")(s"http://$localHttpbin/get?hello=world&foo=baz")
3535

3636
val res1 = requests.send("put")(
37-
"https://httpbin.org/put",
37+
s"http://$localHttpbin/put",
3838
data = Map("hello" -> "world", "foo" -> "baz"),
3939
chunkedUpload = true
4040
).text
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
package requests
2+
3+
import com.dimafeng.testcontainers.GenericContainer
4+
import org.testcontainers.containers.wait.strategy.Wait
5+
import utest._
6+
7+
abstract class HttpbinTestSuite extends TestSuite {
8+
9+
private val containerDef = GenericContainer.Def(
10+
"kennethreitz/httpbin",
11+
exposedPorts = Seq(80),
12+
waitStrategy = Wait.forHttp("/")
13+
)
14+
private val container = containerDef.start()
15+
16+
val localHttpbin: String = s"${container.containerIpAddress}:${container.mappedPort(80)}"
17+
18+
override def utestAfterAll(): Unit = {
19+
container.stop()
20+
}
21+
}

requests/test/src/requests/RequestTests.scala

+47-45
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,8 @@ package requests
33
import utest._
44
import ujson._
55

6-
object RequestTests extends TestSuite{
6+
object RequestTests extends HttpbinTestSuite {
7+
78
val tests = Tests{
89
test("matchingMethodWorks"){
910
val requesters = Seq(
@@ -13,18 +14,18 @@ object RequestTests extends TestSuite{
1314
requests.put
1415
)
1516

16-
for(protocol <- Seq("http", "https")){
17+
for(baseUrl <- Seq(s"http://$localHttpbin", "https://httpbin.org")){
1718
for(r <- requesters){
1819
for(r2 <- requesters){
19-
val res = r(s"$protocol://httpbin.org/${r2.verb.toLowerCase()}", check = false)
20+
val res = r(s"$baseUrl/${r2.verb.toLowerCase()}", check = false)
2021
if (r.verb == r2.verb) assert(res.statusCode == 200)
2122
else assert(res.statusCode == 405)
2223

2324
if (r.verb == r2.verb){
24-
val res = r(s"$protocol://httpbin.org/${r2.verb.toLowerCase()}")
25+
val res = r(s"$baseUrl/${r2.verb.toLowerCase()}")
2526
assert(res.statusCode == 200)
2627
}else intercept[RequestFailedException]{
27-
r(s"$protocol://httpbin.org/${r2.verb.toLowerCase()}")
28+
r(s"$baseUrl/${r2.verb.toLowerCase()}")
2829
}
2930
}
3031
}
@@ -34,26 +35,26 @@ object RequestTests extends TestSuite{
3435
test("params"){
3536
test("get"){
3637
// All in URL
37-
val res1 = requests.get("https://httpbin.org/get?hello=world&foo=baz").text()
38+
val res1 = requests.get(s"http://$localHttpbin/get?hello=world&foo=baz").text()
3839
assert(read(res1).obj("args") == Obj("foo" -> "baz", "hello" -> "world"))
3940

4041
// All in params
4142
val res2 = requests.get(
42-
"https://httpbin.org/get",
43+
s"http://$localHttpbin/get",
4344
params = Map("hello" -> "world", "foo" -> "baz")
4445
)
4546
assert(read(res2).obj("args") == Obj("foo" -> "baz", "hello" -> "world"))
4647

4748
// Mixed URL and params
4849
val res3 = requests.get(
49-
"https://httpbin.org/get?hello=world",
50+
s"http://$localHttpbin/get?hello=world",
5051
params = Map("foo" -> "baz")
5152
).text()
5253
assert(read(res3).obj("args") == Obj("foo" -> "baz", "hello" -> "world"))
5354

5455
// Needs escaping
5556
val res4 = requests.get(
56-
"https://httpbin.org/get?hello=world",
57+
s"http://$localHttpbin/get?hello=world",
5758
params = Map("++-- lol" -> " !@#$%")
5859
)
5960
assert(read(res4).obj("args") == Obj("++-- lol" -> " !@#$%", "hello" -> "world"))
@@ -63,7 +64,7 @@ object RequestTests extends TestSuite{
6364
test("multipart"){
6465
for(chunkedUpload <- Seq(true, false)) {
6566
val response = requests.post(
66-
"http://httpbin.org/post",
67+
s"http://$localHttpbin/post",
6768
data = MultiPart(
6869
MultiItem("file1", "Hello!".getBytes, "foo.txt"),
6970
MultiItem("file2", "Goodbye!")
@@ -79,76 +80,77 @@ object RequestTests extends TestSuite{
7980
test("cookies"){
8081
test("session"){
8182
val s = requests.Session(cookieValues = Map("hello" -> "world"))
82-
val res1 = s.get("https://httpbin.org/cookies").text().trim
83+
val res1 = s.get(s"http://$localHttpbin/cookies").text().trim
8384
assert(read(res1) == Obj("cookies" -> Obj("hello" -> "world")))
84-
s.get("https://httpbin.org/cookies/set?freeform=test")
85-
val res2 = s.get("https://httpbin.org/cookies").text().trim
85+
s.get(s"http://$localHttpbin/cookies/set?freeform=test")
86+
val res2 = s.get(s"http://$localHttpbin/cookies").text().trim
8687
assert(read(res2) == Obj("cookies" -> Obj("freeform" -> "test", "hello" -> "world")))
8788
}
8889
test("raw"){
89-
val res1 = requests.get("https://httpbin.org/cookies").text().trim
90+
val res1 = requests.get(s"http://$localHttpbin/cookies").text().trim
9091
assert(read(res1) == Obj("cookies" -> Obj()))
91-
requests.get("https://httpbin.org/cookies/set?freeform=test")
92-
val res2 = requests.get("https://httpbin.org/cookies").text().trim
92+
requests.get(s"http://$localHttpbin/cookies/set?freeform=test")
93+
val res2 = requests.get(s"http://$localHttpbin/cookies").text().trim
9394
assert(read(res2) == Obj("cookies" -> Obj()))
9495
}
9596
test("space"){
9697
val s = requests.Session(cookieValues = Map("hello" -> "hello, world"))
97-
val res1 = s.get("https://httpbin.org/cookies").text().trim
98+
val res1 = s.get(s"http://$localHttpbin/cookies").text().trim
9899
assert(read(res1) == Obj("cookies" -> Obj("hello" -> "hello, world")))
99-
s.get("https://httpbin.org/cookies/set?freeform=test+test")
100-
val res2 = s.get("https://httpbin.org/cookies").text().trim
100+
s.get(s"http://$localHttpbin/cookies/set?freeform=test+test")
101+
val res2 = s.get(s"http://$localHttpbin/cookies").text().trim
101102
assert(read(res2) == Obj("cookies" -> Obj("freeform" -> "test test", "hello" -> "hello, world")))
102103
}
103104
}
104105

105106
test("redirects"){
106107
test("max"){
107-
val res1 = requests.get("https://httpbin.org/absolute-redirect/4")
108+
val res1 = requests.get(s"http://$localHttpbin/absolute-redirect/4")
108109
assert(res1.statusCode == 200)
109-
val res2 = requests.get("https://httpbin.org/absolute-redirect/5")
110+
val res2 = requests.get(s"http://$localHttpbin/absolute-redirect/5")
110111
assert(res2.statusCode == 200)
111-
val res3 = requests.get("https://httpbin.org/absolute-redirect/6", check = false)
112+
val res3 = requests.get(s"http://$localHttpbin/absolute-redirect/6", check = false)
112113
assert(res3.statusCode == 302)
113-
val res4 = requests.get("https://httpbin.org/absolute-redirect/6", maxRedirects = 10)
114+
val res4 = requests.get(s"http://$localHttpbin/absolute-redirect/6", maxRedirects = 10)
114115
assert(res4.statusCode == 200)
115116
}
116117
test("maxRelative"){
117-
val res1 = requests.get("https://httpbin.org/relative-redirect/4")
118+
val res1 = requests.get(s"http://$localHttpbin/relative-redirect/4")
118119
assert(res1.statusCode == 200)
119-
val res2 = requests.get("https://httpbin.org/relative-redirect/5")
120+
val res2 = requests.get(s"http://$localHttpbin/relative-redirect/5")
120121
assert(res2.statusCode == 200)
121-
val res3 = requests.get("https://httpbin.org/relative-redirect/6", check = false)
122+
val res3 = requests.get(s"http://$localHttpbin/relative-redirect/6", check = false)
122123
assert(res3.statusCode == 302)
123-
val res4 = requests.get("https://httpbin.org/relative-redirect/6", maxRedirects = 10)
124+
val res4 = requests.get(s"http://$localHttpbin/relative-redirect/6", maxRedirects = 10)
124125
assert(res4.statusCode == 200)
125126
}
126127
}
127128

128129
test("test_reproduction"){
129-
requests.get("http://httpbin.org/status/304").text()
130+
requests.get(s"http://$localHttpbin/status/304").text()
130131

131132
}
132133
test("streaming"){
133-
val res1 = requests.get("http://httpbin.org/stream/5").text()
134+
val res1 = requests.get(s"http://$localHttpbin/stream/5").text()
134135
assert(res1.linesIterator.length == 5)
135-
val res2 = requests.get("http://httpbin.org/stream/52").text()
136+
val res2 = requests.get(s"http://$localHttpbin/stream/52").text()
136137
assert(res2.linesIterator.length == 52)
137138
}
138139

139140
test("timeouts"){
140141
test("read"){
141142
intercept[TimeoutException] {
142-
requests.get("https://httpbin.org/delay/1", readTimeout = 10)
143+
requests.get(s"http://$localHttpbin/delay/1", readTimeout = 10)
143144
}
144-
requests.get("https://httpbin.org/delay/1", readTimeout = 2000)
145+
requests.get(s"http://$localHttpbin/delay/1", readTimeout = 2000)
145146
intercept[TimeoutException] {
146-
requests.get("https://httpbin.org/delay/3", readTimeout = 2000)
147+
requests.get(s"http://$localHttpbin/delay/3", readTimeout = 2000)
147148
}
148149
}
149150
test("connect"){
150151
intercept[TimeoutException] {
151-
requests.get("https://httpbin.org/delay/1", connectTimeout = 1)
152+
// use remote httpbin.org so it needs more time to connect
153+
requests.get(s"https://httpbin.org/delay/1", connectTimeout = 1)
152154
}
153155
}
154156
}
@@ -167,38 +169,38 @@ object RequestTests extends TestSuite{
167169
}
168170

169171
test("decompress"){
170-
val res1 = requests.get("https://httpbin.org/gzip")
171-
assert(read(res1.text()).obj("headers").obj("Host").str == "httpbin.org")
172+
val res1 = requests.get(s"http://$localHttpbin/gzip")
173+
assert(read(res1.text()).obj("headers").obj("Host").str == localHttpbin)
172174

173-
val res2 = requests.get("https://httpbin.org/deflate")
174-
assert(read(res2).obj("headers").obj("Host").str == "httpbin.org")
175+
val res2 = requests.get(s"http://$localHttpbin/deflate")
176+
assert(read(res2).obj("headers").obj("Host").str == localHttpbin)
175177

176-
val res3 = requests.get("https://httpbin.org/gzip", autoDecompress = false)
178+
val res3 = requests.get(s"http://$localHttpbin/gzip", autoDecompress = false)
177179
assert(res3.bytes.length < res1.bytes.length)
178180

179-
val res4 = requests.get("https://httpbin.org/deflate", autoDecompress = false)
181+
val res4 = requests.get(s"http://$localHttpbin/deflate", autoDecompress = false)
180182
assert(res4.bytes.length < res2.bytes.length)
181183

182184
(res1.bytes.length, res2.bytes.length, res3.bytes.length, res4.bytes.length)
183185
}
184186

185187
test("compression"){
186188
val res1 = requests.post(
187-
"https://httpbin.org/post",
189+
s"http://$localHttpbin/post",
188190
compress = requests.Compress.None,
189191
data = new RequestBlob.ByteSourceRequestBlob("Hello World")
190192
)
191193
assert(res1.text().contains(""""Hello World""""))
192194

193195
val res2 = requests.post(
194-
"https://httpbin.org/post",
196+
s"http://$localHttpbin/post",
195197
compress = requests.Compress.Gzip,
196198
data = new RequestBlob.ByteSourceRequestBlob("I am cow")
197199
)
198200
assert(read(new String(res2.bytes))("data").toString.contains("data:application/octet-stream;base64,H4sIAAAAAA"))
199201

200202
val res3 = requests.post(
201-
"https://httpbin.org/post",
203+
s"http://$localHttpbin/post",
202204
compress = requests.Compress.Deflate,
203205
data = new RequestBlob.ByteSourceRequestBlob("Hear me moo")
204206
)
@@ -208,7 +210,7 @@ object RequestTests extends TestSuite{
208210

209211
test("headers"){
210212
test("default"){
211-
val res = requests.get("https://httpbin.org/headers").text()
213+
val res = requests.get(s"http://$localHttpbin/headers").text()
212214
val hs = read(res)("headers").obj
213215
assert(hs("User-Agent").str == "requests-scala")
214216
assert(hs("Accept-Encoding").str == "gzip, deflate")
@@ -306,7 +308,7 @@ object RequestTests extends TestSuite{
306308
// to the server. This preserves the 0.8.x behavior, and can always be overriden
307309
// by passing a comma-separated list of headers instead
308310
test("duplicateHeaders"){
309-
val res = requests.get("https://httpbin.org/get", headers = Seq("x-y" -> "a", "x-y" -> "b"))
311+
val res = requests.get(s"http://$localHttpbin/get", headers = Seq("x-y" -> "a", "x-y" -> "b"))
310312
assert(ujson.read(res)("headers")("X-Y") == Str("b")) // make sure it's not "a,b"
311313
}
312314
}

0 commit comments

Comments
 (0)