Scala Specs2: how to get current test name? - scala

I'm working with Scala project, using Specs2 for testing.
How could I know the test name i'm currently within it (form the test context)?
This is the code structure of my tests:
class TestsE2E{
trait Context extends E2EScope {
...
}
"Test" should {
"do stuff" in new Context {
...
}
}
}

If you just use the test name to log it, you can create a custom ExamplesFactory to intercept the name:
import org.specs2.mutable.{FragmentsBuilder, ExamplesFactory}
trait TestNameLogger extends ExamplesFactory { this: FragmentsBuilder =>
override implicit def exampleFactory: ExampleFactory = new TestNameLoggerMutableExampleFactory
class TestNameLoggerMutableExampleFactory extends MutableExampleFactory {
override def newExample(e: Example): Example = {
println(e.desc.raw)
super.newExample(e)
}
}
}
This solution is a bit involved and the API for doing this will change with the upcoming specs2 3.0. Another alternative is to create your own Notifier.

Related

How to create mock object of a class which is package private

I have a class. It has a companion object A with a factory method.
class A private[somepackage](x: Int) {
}
object A {
def createA(y: Int): A = {
new A(y)
}
}
Now I need to create the mock object of A in a scalatest file which is in a different package.
When I give
private val a = mock[A] --> I get compilation error.
constructor A in class A cannot be accessed in <<somewhere>>.
Is there a better way to mock the object ??
In your test sources, create a test double in the same package:
package somepackage
class MockableA extends A(0)
then just create a mock[MockableA] in your tests and continue as usual.
But the answer with a proxy/facade should work too if you are willing to change production sources to facilitate tests.
Consider using a proxy to access class A, and stub/mock that proxy class instead.
E.g., if A.doStuff is what you want to mock/stub, and A.accessStuff is what you need in your code, create a class
class ADecorated(underlying: A) {
def doStuff() {
underlying.doStuff()
// whatever I want to do
}
def accessStuff() {
x = underlying.accessStuff()
// do something else and return
}
// Any other method you want to use
}
Replace usage of A.createA with new ADecorated(A.createA()). ADecorated is what you work with now

Programmatically adding new tests via ScalaTest

I have a set of input cases stored in a file.
I would like each case to be a specific scalatest "test", i.e., reported in the console as an individual test and failed individually.
Unfortunately, experimentation and Google suggest that this capability might not be present?
E.g., this seems to be the common case (eliding for simplicity)
class MyTestingGoop extends FunSuite {
val input : Seq[SpecificTestCase] = ...
test("input data test") {
forAll(input) { case => ... }
}
//...
}
Ideally, each case presents as a separate test. How can this be done with ScalaTest?
You can do this:
class MyTestingGoop extends FunSuite {
val input : Seq[SpecificTestCase] = ...
forAll(input) {
test("testing input" + input) {
// do something with the test
}
}
}
The only limit is that input has a unique toString.
Basically calling test in Funsuite registers the test and later runs it so as long as your test creation is done as part of the class construction and each test has a unique string, you should be fine.

how plugin works with inject and object instead of class in play 2.4

I need to migrate the play mailer plugin for play 2.4.I checked some samples for play 2.4 and found that all the samples uses classes for plugin. I don't want to convert it to class. Is there any way for it to work with Object?
Sample
class MyComponent #Inject() (mailerClient: MailerClient) {
def sendEmail {
val email = Email(......)
......
mailerClient.send(email)
}
}
Original Code
object MailHandler{
def sendEmail(to: String) = {
try {
val email = play.api.libs.mailer.Email(...)
MailerPlugin.send(email)
}catch{
case ex:Exception=>PlayLogger.instance.error(ex.getMessage)
}
}
I assume you use an object instead of a class in order to make it a singleton.
There is a special annotation for singletons (-> #Singleton) which makes sure there is only one instance of your class created.
Although they still use an actual class instead of an object.
An example could look like this:
import javax.inject._
#Singleton
class MailerClient {
def sendEmail(to: String) = {
try {
val email = play.api.libs.mailer.Email(...)
MailerPlugin.send(email)
}catch{
case ex:Exception=>PlayLogger.instance.error(ex.getMessage)
}
}
}
Have a look at the documentation:
https://www.playframework.com/documentation/2.4.x/ScalaDependencyInjection#Singletons

How to use JUnit's #Rule annotation with Scala Specs2 tests?

In our project we use Scala Specs2 together with Selenium.
I'm trying to implement screenshot-on-failure mechanism "in a classic way (link)" for my tests, using JUnit annotations, but, the rule doesn't called on test failure at all.
The structure of the test is as follows:
class Tests extends SpecificationWithJUnit{
trait Context extends LotsOfStuff {
#Rule
val screenshotOnFailRule = new ScreenshotOnFailRule(driver)
}
"test to verify stuff that will fail" should {
"this test FAILS" in new Context {
...
}
}
The ScreenshotOnFailRule looks like this:
class ScreenshotOnFailRule (webDriver: WebDriver) extends TestWatcher {
override def failed(er:Throwable, des:Description) {
val scrFile = webDriver.asInstanceOf[TakesScreenshot].getScreenshotAs(OutputType.FILE)
FileUtils.copyFile(scrFile, new File(s"/tmp/automation_screenshot${Platform.currentTime}.png"))
}
}
I understand that probably it doesn't work now because the tests aren't annotated with #Test annotation.
Is it possible to annotate the Specs2 tests with JUnit #Rule annotation?
According to this question it seems as if JUnit Rules aren't supported. But you could try to make use of the AroundExample trait:
import org.specs2.execute.{AsResult, Result}
import org.specs2.mutable._
import org.specs2.specification.AroundExample
class ExampleSpec extends Specification with AroundExample {
// execute tests in sequential order
sequential
"The 'Hello world' string" should {
"contain 11 characters" in {
"Hello world" must have size (10)
}
// more tests..
}
override protected def around[T](t: => T)(implicit ev: AsResult[T]): Result = {
try {
AsResult.effectively(t)
} catch {
case e: Throwable => {
// take screenshot here
throw e
}
}
}
}

Scala Dependency Injection with Cake Pattern

I've been following this article which describes how to achieve dependency injection in Scala via the Cake Pattern:
http://jonasboner.com/real-world-scala-dependency-injection-di/
I'm kind of new to Scala and I admit some of it went over my head, so far I've got the following working:
// Setup the component and interface
trait AccountRepositoryComponent {
val accountRepository: AccountRepositoryInterface
trait AccountRepositoryInterface {
def message: String
}
}
// An implementation
trait MyAccountRepositoryComponent extends AccountRepositoryComponent {
object AccountRepository extends AccountRepositoryInterface {
def message: String = "Hello"
}
}
// Object to configure which implementations to use and retrieve them
object ComponentRegistry extends MyAccountRepositoryComponent {
val accountRepository = AccountRepository
}
// Example service using the above
object AccountService {
val repo = ComponentRegistry.accountRepository
def say: String = repo.message
}
println(AccountService.say)
What I'm failing to understand is how I would now pass in a fake repository to Account Service, say to change the output to "Test" rather than "Hello"?
There are various ways this could be modified to achieve a workable result, depending on what counts as a workable result for your situation. I'll go through a simpler possibility here.
First, the ComponentRegistry needs to become a trait, so it can be mixed in to the AccountService:
// Trait to configure which component implementations to use and retrieve them
object ComponentRegistry extends MyAccountRepositoryComponent {
val accountRepository = AccountRepository
}
// Example service using the above
object AccountService extends ComponentRegistry {
def say: String = accountRepository.message
}
println(AccountService.say)
This should print "Hello" as before. To set up a test case, add the following:
// Test implementation
trait TestAccountRepositoryComponent extends AccountRepositoryComponent {
object AccountRepository extends AccountRepositoryInterface {
def message: String = "Test"
}
}
// trait to configure test component implementations
trait TestComponentRegistry extends TestAccountRepositoryComponent {
val accountRepository = AccountRepository
}
Now we can set up a service that uses the test components:
// Example service using the above
object AccountService extends TestComponentRegistry {
//val repo = ComponentRegistry.accountRepository
def say: String = accountRepository.message
}
println(AccountService.say)
This should print "Test".
Note that you would probably want your AccountService to define its functionality in terms of other mixins/traits, which would expect the appropriate components to be available (layered into the "cake"), but wouldn't know which implementation was in use. Eg:
trait CustomerApi {
self: AccountRepositoryComponent => // Expects an implementation of AccountRepositoryComponent to be mixed in
def say: String = accountRepository.message
}
Now the method say is implemented without knowing what version of AccountRepository it will interact with, but knowing one must be provided (checked at compile time). So we can write:
object AccountService extends CustomerApi with ComponentRegistry
object TestAccountService extends CustomerApi with TestComponentRegistry
Calling println(AccountService.say) will generate "Hello", while calling println(TestAccountService.say) will generate "Test".
This post provides a succinct example of that (followed by an interesting alternative).