So einfach geht modernes Roaming fuer Notes und Nomad.pdf
Specs2
1. Specs2
Library for writing Acceptance And
Unit Tests
Piyush Mishra
Software Consultant
Knoldus Software LLP
2. Topics Covered
What is Specs2
The design principles of specs2
Unit Specifications
Acceptance Specifications
Matchers
Runners
3. What is Specs2
Specs is a DSL in Scala for doing BDD
(Behavior-Driven -Development).
4. Design Principles of Specs2
Do not use mutable variables
Use a simple structure
Control the dependencies (no cycles)
Control the scope of implicits
5. Guide to write Unit Specifications
Unit specifications
Extend the org.specs2.mutable.Specification trait
are mutable
Use should / in format in creates an Example object
containing a Result should creates a group of Example
objects
6. Creating Unit Specifications
package knoldus.Specs2
import org.specs2.mutable.Specification
import org.specs2.mutable
class HelloWorldSpec extends Specification {
"The 'Hello world' string" should {
"contain 11 characters" in {
"Hello world" must have size(11)
}
"start with 'Hello'" in {
"Hello world" must startWith("Hello")
}
"end with 'world'" in {
"Hello world" must endWith("world")
}
}
}
7. Guide to write Acceptance
Specifications
Extend the org.specs2.Specification trait
are functional when extending the default
org.specs2.Specification trait
Must define a method called is that takes a Fragments
object, which is composed of an optional SpecStart , a list of
Fragment objects an options SpecEnd
8. Creating Acceptance Specifications
package knoldus.Specs2
import org.specs2._
class HelloWorldAcceptanceSpec extends Specification {
def is =
"This is a specification to check the 'Hello world' string" ^
p^
"The 'Hello world' string should" ^
"contain 11 characters" ! e1 ^
"start with 'Hello'" ! e2 ^
"end with 'world'" ! e3 ^
end
def e1 = "Hello world" must have size (11)
def e2 = "Hello world" must startWith("Hello")
def e3 = "Hello world" must endWith("world")
}
9. Acceptance Specifications are
functional
The default Specification trait in specs2 is functional: the Result of an example is
always given by the last statement of its body. This example will never fail
because the first expectation is "lost":
"my example on strings" ! e1 // will never fail!
def e1 = {
"hello" must have size(10000) // because this expectation will not be
returned,...
"hello" must startWith("hell")
}
So the correct way of writing the example is:
"my example on strings" ! e1 // will fail
def e1 = "hello" must have size(10000) and
startWith("hell")
10. Matchers
there are many ways to define expectations in specs2. You
can define expectations with anything that returns a Result:
Boolean
Standard result
Matcher result
Scalacheck property
Mock expectation
DataTable
Forms
11. Boolean Result
this is the simplest kind of result you can define for an
expectation but also the least expressive!
Here's an example:
"This is hopefully true" ! (1 != 2)
This can be useful for simple expectations but a failure will
give few information on what went wrong:
"This is hopefully true" ! (2 != 2) // fails with 'the value is
false',...
12. Standard Result
Some standard results can be used when you need specific result
meanings:
success: the example is ok
failure: there is a non-met expectation
anError: a non-expected exception occurred
skipped: the example is skipped possibly at runtime because
some conditions are not met. A more specific message can
be created with Skipped("my message")
pending: usually means "not implemented yet", but a specific
message can be created with Pending("my message")
Two additional results are also available to track the progress of
features:
done: a Success with the message "DONE"
todo: a Pending with the message "TODO"
13. Matcher Result
the most common matchers are automatically available when
extending the Specification trait:
1 must beEqualTo(1) the normal way
1 must be_==(1) with a shorter matcher
1 must_== 1 my favorite!
1 mustEqual 1 if you dislike underscores
1 should_== 1 for should lovers
1 === 1 the ultimate shortcut
1 must be equalTo(1) with a literate style
14. Iterable Matchers
specs 1.x:
val list = List(1, 2, 3)
list must have size(3)
list must containInOrder(1, 2, 3)
specs2
Using only and inOrder we can state this in one shot:
List(1, 2, 3) must contain(1, 2, 3).only.inOrder
15. JSON Matchers
specs 1.x:
val list = List(1, 2, 3)
list must have size(3)
list must containInOrder(1, 2, 3)
specs2
Using only and inOrder we can state this in one shot:
List(1, 2, 3) must contain(1, 2, 3).only.inOrder
16. JSON Matchers
/(value) looks for a value at the root of an Array
"""["name", "Joe" ]""" must /("name")
/(key -> value) looks for a pair at the root of a Map
"""{ "name": "Joe" }""" must /("name" -> "Joe")
"""{ "name": "Joe" }""" must not /("name2" -> "Joe")
17. Mocking
import org.specs2.mock._
class MockitoSpec extends Specification { def is =
"A java list can be mocked" ^
"You can make it return a stubbed value" ! c().stub^
"You can verify that a method was called" ! c().verify^
"You can verify that a method was not called" ! c().verify2^
end
case class c() extends Mockito {
val m = mock[java.util.List[String]] // a concrete class would be mocked with:
mock[new java.util.LinkedList[String]]
def stub = {
m.get(0) returns "one" // stub a method call with a return value
m.get(0) must_== "one" // call the method
}
def verify = {
m.get(0) returns "one" // stub a method call with a return value
m.get(0) // call the method
there was one(m).get(0) // verify that the call happened
}
def verify2 = there was no(m).get(0) // verify that the call never happened
}
}
18. Forms
Forms are a way to represent domain objects or services, and declare expected values in
a tabular format. Forms can be designed as reusable pieces of specification where
complex forms can be built out of simple ones.
class SpecificationWithForms extends Specification with Forms { def is =
"The address must be retrieved from the database with the proper street and
number" ^
Form("Address").
tr(prop("street", actualStreet(123), "Oxford St")).
tr(prop("number", actualNumber(123), 20)) ^
end
}
19. Running Specification Using Junit
With Junit We can run test as this
import org.junit.runner._
import runner._
@RunWith(classOf[JUnitRunner])
class WithJUnitSpec extends Specification {
"My spec" should {
"run in JUnit too" in {
success
}
}
}
20. Running Specification Using SBT
With Sbt We can run test as this
For console OutPut Add this line in your build.sbt
testOptions in Test += Tests.Argument("console")
And run
test-only classFileName – console
For html output
Add dependencies
"org.pegdown" % "pegdown" % "1.0.2"
testOptions in Test += Tests.Argument("html")
And run
test-only classFileName – html
For html and console output
testOptions in Test += Tests.Argument("html",console)
And run
test-only classFileName – html console