Scala - kort introduktion
Gatling
Opfundet af: Martin Odersky professor in programming methods at EPFL, Schweitz
Generic Java 1998/99
Multi-paradigme
Installation
Installer via SDKMan http://sdkman.io/
Scala
scala hello-world.scala
scalac hello-world.scala
println("Hello world!")
// Object er en singleton class
object Main {
def main(args: Array[String]): Unit = {
println("Main...")
}
}
// App er en Trait der sparer os for at skrive main...
object HelloWorld extends App {
println("Hello, world!")
}
// Mutable variabel
var x : Int = 100
// Immutable værdi (readonly)
val y : Int = 200
// Uden type angivelser
var a = 300
val b = 400
println("X: " + x + ", Y: " + y + ", A: " + a + ", B: " + b)
// Funktions definition
def upperCase(name : String) : String = { return name.toUpperCase() }
// Return er optional for funktioner og det samme er return typen
def lowerCase(name : String) = { name.toLowerCase() }
// One-liners kræver ikke '{}' om funktions body
def add(x : Int, y : Int) : Int = x + y
// Params er immutable (val) og understøtter default værdier
def prefix(name : String, prefix : String = "Mr. ") = {
prefix + name
}
// Implicit Unit return type
def short() { println("Short") }
abstract class X (val navn : String) {
var x : Int = 100
def getName() : String = navn
def foobar() {}
}
class Y(override val navn : String) extends X(navn) {
println("Constructor code")
def this() = this("auxilary constructor")
override def foobar() = println("foo")
}
val a = new Y("bar")
a.foobar()
val b = new Y()
println(b.getName())
static
keyword som Java, i stedet har de object
object
er en singleton class
// Companion objects
class Bar(foo: String) {
def foo() : String = foo
}
object Bar {
def apply(foo: String) = new Bar(foo)
}
// Factory metode, sparer os for new
def x = Bar("Pub")
println(x.foo)
f(x) applying function f to its argument x
trait T {
def foo() = "bar"
}
class P {
def parent() = "parent"
}
class C extends P with T {}
val cpt = new C()
val pt = new P() with T
println(cpt.foo)
println(cpt.parent())
println(pt.foo())
class C {
def bar() = "foo"
}
// case sparer os for en del boilerplate code ved at
// tilføjer en række metoder: toString(), hashCode(), equals()
case class D(val f : String = "Hest", val g : String = "vogn") extends C {}
val c = new C()
val d = D()
println(c)
println(d)
Bemærk: case benyttes også ved pattern matching
import scala.language.implicitConversions
case class Point(x : Int, y : Int) {
// Operator overloading
def * (mul: Point) : Point = {
new Point(x * mul.x, y * mul.y)
}
def * (mul: Int) : Point = {
new Point(x * mul, y * mul)
}
}
implicit def intToPoint(z : Int) : Point = new Point(z, z)
def p1 = new Point(2, 4)
println(p1 * p1) // Out: Point(4,16)
// Mulig uden implicit
println(p1 * 3) // Out: Point(6,12)
// Kun med implicit
println(3 * p1) // Out: Point(6,12)
!
hvorved der placeres et objekt på en køEksempel lånt fra bogen: Seven Languages in Seven Weeks
import scala.io._
import scala.actors._
import Actor._
object PageLoader {
def getPageSize(url : String) = Source.fromURL(url).mkString.length
}
val urls = List("http://www.amazon.co.uk/",
"http://www.bbc.co.uk/",
"http://www.dr.dk/",
"http://www.cnn.com/" )
def timeMethod(method: () => Unit) = {
val start = System.nanoTime
method()
val end = System.nanoTime
println("Method took " + (end - start)/1000000000.0 + " seconds.")
}
def getPageSizeConcurrently() = {
val caller = self
for(url <- urls) {
actor { caller ! (url, PageLoader.getPageSize(url)) }
}
for(i <- 1 to urls.size) {
receive {
case (url, size) =>
println("Size for " + url + ": " + size)
}
}
}
// START:script
timeMethod { getPageSizeConcurrently }
Scala har en del features der gør det velegnet til DSL’er
Download og unzip
bin/gatling.sh
eller bin\gatling.bat
Build tool
Bygget på
Gatling har et begreb der hedder Scenarier
bin/recorder.sh
eller bin\recorder.bat
)Listening port
til at proxy igennemClass Name
Output folder
Evt. rediger Blacklist
og Infer html resources?
package dk.workbench
import io.gatling.core.Predef._
import io.gatling.http.Predef._
import scala.concurrent.duration._
class BasicSimulation extends Simulation {
val httpConf = http
.baseURL("http://workbench.dk")
.acceptHeader("text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8")
.userAgentHeader("Mozilla/5.0 (Windows NT 5.1; rv:31.0) Gecko/20100101 Firefox/31.0")
val scn = scenario("BasicSimulation")
.exec(http("request_index")
.get("/").check(substring("hello world")))
.pause(5)
setUp(
scn.inject(atOnceUsers(1))
)
.assertions(
forAll.responseTime.max.lessThan(6),
global.failedRequests.percent.lessThan(2)
)
.protocols(httpConf)
}
mvn gatling:execute -Dgatling.simulationClass=dk.workbench.BasicSimulation
gatling.sh
som scanner efter tests ud fra $GATLING_HOME
$ bin/gatling.sh
GATLING_HOME is set to /home/thomas/Downloads/gatling-charts-highcharts-bundle-2.1.7
Choose a simulation number:
[0] RecordedSimulation
[1] computerdatabase.BasicSimulation
[2] computerdatabase.advanced.AdvancedSimulationStep01
[3] computerdatabase.advanced.AdvancedSimulationStep02
[4] computerdatabase.advanced.AdvancedSimulationStep03
[5] computerdatabase.advanced.AdvancedSimulationStep04
[6] computerdatabase.advanced.AdvancedSimulationStep05
Hvad er det man ønsker at teste?
B: Webserver (Apache, Tomcat, Nginx…)
D: Database (MySQL, PostgreSQL…)
Gatling Scala API
Point-n-click
Gatling: http://gatling.io/
Scala: http://www.scala-lang.org
/