Skip to content

Instantly share code, notes, and snippets.

@mrpotes
Last active January 5, 2016 01:38
Show Gist options
  • Star 3 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save mrpotes/6029082 to your computer and use it in GitHub Desktop.
Save mrpotes/6029082 to your computer and use it in GitHub Desktop.
val recorder = new Recorder
@Rule def recorderDef = recorder
test("weather for london") _ using betamax("tape name") { ... }
import co.freeside.betamax.TapeMode
import co.freeside.betamax.Recorder
import co.freeside.betamax.proxy.jetty.ProxyServer
trait Betamax extends Wrapped{
def betamax(tape: String, mode: Option[TapeMode] = None)(testFun: => Unit) = {
println("Starting Betamax")
val recorder = new Recorder
val proxyServer = new ProxyServer(recorder)
recorder.insertTape(tape)
recorder.getTape.setMode(mode.getOrElse(recorder.getDefaultMode()))
proxyServer.start()
try {
testFun
} finally {
recorder.ejectTape()
proxyServer.stop()
}
}
}
import org.scalatest.FunSuite
import co.freeside.betamax.TapeMode
class WeatherSuite extends FunSuite with Betamax {
test("weather for london using betamax") _ using betamax("scala-test", Some(TapeMode.READ_ONLY)) {
assert(WeatherClient.weatherFor("london,gb").location === "London, GB")
}
}
import co.freeside.betamax.Betamax;
import co.freeside.betamax.Recorder;
import org.junit.*;
public class MyTest {
@Rule public Recorder recorder = new Recorder();
@Betamax(tape="my tape")
@Test
public void testMethodThatAccessesExternalWebService() {
// test me
}
}
test("weather for london") with Betamax("tape name") {
assert(WeatherClient.weatherFor("london,gb").location === "London, GB")
}
trait Betamax {
protected def test(testName: String, testTags: Tag*)(testFun: => Unit)
def testWithBetamax(tape: String, mode: Option[TapeMode] = None)(testName: String, testTags: Tag*)(testFun: => Unit) = {
test(testName, testTags: _*) {
val recorder = new Recorder
val proxyServer = new ProxyServer(recorder)
recorder.insertTape(tape)
recorder.getTape.setMode(mode.getOrElse(recorder.getDefaultMode()))
proxyServer.start()
try {
testFun
} finally {
recorder.ejectTape()
proxyServer.stop()
}
}
}
}
import org.scalatest.FunSuite
class WeatherSuite extends FunSuite {
test("weather for london") {
assert(WeatherClient.weatherFor("london,gb").location === "London, GB")
}
}
def withTape(tapeName:String, functionUnderTest:() => Any) = {
synchronized {
val recorder = new Recorder
val proxyServer = new ProxyServer(recorder)
recorder.insertTape(tapeName)
proxyServer.start()
try {
functionUnderTest()
} finally {
recorder.ejectTape()
proxyServer.stop()
}
}
}
".apply" should {
"fetch and parse JSON from the Twitter endpoint" in {
val url = "http://www.buzzfeed.com/despicableme2/15-reasons-we-wish-we-were-steve-carell/"
var tw = Twitter(url)
tw.url must_== url
tw.tweets must_== 29
}
}
"The Weather Client" should {
"find London, GB" in Betamax("weather client") {
WeatherClient.weatherFor("london,gb").location must beEqualTo("London, GB")
}
}
var tw:Twitter = null
BetamaxHelper.withTape("Twitter.apply", () => {
tw = Twitter(url)
})
package specs2
import org.specs2.mutable.Around
import org.specs2.execute.AsResult
import co.freeside.betamax.Recorder
import co.freeside.betamax.proxy.jetty.ProxyServer
import co.freeside.betamax.TapeMode
class Betamax(tape: String, mode: Option[TapeMode] = None) extends Around {
def around[T: AsResult](t: => T) = Betamax.around(t, tape, mode)
}
object Betamax {
// syntactic sugar does away with 'new' in tests
def apply(tape: String, mode: Option[TapeMode] = None) = new Betamax(tape, mode)
def around[T: AsResult](t: => T, tape: String, mode: Option[TapeMode]) = {
synchronized {
val recorder = new Recorder
val proxyServer = new ProxyServer(recorder)
recorder.insertTape(tape)
recorder.getTape.setMode(mode.getOrElse(recorder.getDefaultMode()))
proxyServer.start()
try {
AsResult(t)
} finally {
recorder.ejectTape()
proxyServer.stop()
}
}
}
}
import scala.xml.XML
import java.net.URL
import java.text.SimpleDateFormat
import java.util.Date
object WeatherClient {
val xmlDateTime = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss")
def weatherFor(query: String) = {
val xml = XML.load(new URL("http://api.openweathermap.org/data/2.5/forecast?q="+query+"&mode=xml"))
val forecast = (xml \\ "forecast" \ "time").map(time => {
Forecast(
xmlDateTime parse (time \ "@from").head.text,
xmlDateTime parse (time \ "@to").head.text,
(time \ "symbol" \ "@name").head.text,
(time \ "windSpeed" \ "@name").head.text + " - " + (time \ "windDirection" \ "@code").head.text,
(time \ "temperature" \ "@value").head.text.toDouble.toInt,
(time \ "pressure" \ "@value").head.text.toDouble.toInt,
(time \ "humidity" \ "@value").head.text.toInt,
(time \ "clouds" \ "@all").head.text.toInt
)
})
val loc = xml \ "location"
Result((loc \ "name").head.text + ", " + (loc \ "country").head.text,
(loc \ "location" \ "@latitude").head.text.toDouble,
(loc \ "location" \ "@longitude").head.text.toDouble,
forecast.toList)
}
}
case class Result (location: String, latitude: Double, longitude: Double, forecast: List[Forecast])
case class Forecast (
from: Date,
to: Date,
summary: String,
wind: String,
temp: Int,
pressure: Int,
humidityPercent: Int,
cloudsPercent: Int)
import org.specs2.mutable._
class WeatherSpec extends Specification {
"The Weather Client" should {
"find London, GB" in {
WeatherClient.weatherFor("london,gb").location must beEqualTo("London, GB")
}
}
}
class WeatherSuite extends FunSuite with Betamax {
testWithBetamax("scala-test", Some(TapeMode.READ_ONLY))("weather for london") {
assert(WeatherClient.weatherFor("london,gb").location === "London, GB")
}
}
import org.junit.Test
import org.junit.Assert._
import org.junit.Rule
import co.freeside.betamax.Recorder
import co.freeside.betamax.Betamax
class WeatherTest {
@Rule val recorder = new Recorder
@Betamax(tape="junit")
@Test def findLondon = assertEquals("London, GB", WeatherClient.weatherFor("london,gb").location)
}
trait Wrapped {
implicit def wrapPartialFunction(f: (=> Unit) => Unit) = new wrapped(f)
class wrapped(f: (=> Unit) => Unit) {
def using(f1: => Unit) = f {
f1
}
}
}
@etorreborre
Copy link

If the Betamax context is the same for each example:

class WeatherSpec extends Specification with AroundExample {

  def around[R : AsResult](r: =>R) = Betamax("weather client").around(r)

  "The Weather Client" should {
    "find London, GB" in  {
      WeatherClient.weatherFor("london,gb").location must beEqualTo("London, GB")
    }
  }

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment