Is there a way to take a certain action if my test fails?
I have a test that uses selenium/fluentlinium to fill texts/click buttons and assert results. I'd like to be able to take an action whenever a test condition fails. Something like the following
class TestSpecial extends Specification{
"Website should" {
"do the right thing" in new WithBrowser( webDriver = WebDriverFactory( FIREFOX ) ){
browser.$( ".xyz1" ).text( "a" )
browser.$( ".xyz2" ).click()
browser.$( ".xyz3" ).getText must equalTo( "foo" )
browser.$( ".xyz1" ).text( "b" )
browser.$( ".xyz2" ).click()
browser.$( ".xyz3" ).getText must equalTo( "bar" )
}
onFailure
{
//context remains same, so I can use browser
MySnapshotFunction.takeSnapshot( browser )
}
}
}
Is there a way to make the test throw on failure so that I can take snapshot in the catch block?
I think one way is to use the suggestion given in:
How to do setup/teardown in specs2 when using "in new WithApplication"
Create my own 'WithBrowser' custom implementation that marks each test as failure before starting and requires the user of that implementation to mark the test as passed at the end of test block. The custom implementation in the teardown code takes a snapshot. I have set sight on using this approach, but would welcome any better/simpler solutions to this.
You should be able to use the Around trait:
import org.specs2.mutable._
import org.specs2.execute._
trait TakeSnapshot extends org.specs2.mutable.Around {
def browser: Browser
abstract override def around[R : AsResult](r: =>R) = super.around {
val result = AsResult(r)
if (!result.isSuccess) {
takeSnapshot(browser)
}
result
}
def takeSnapshot(browser: Browser) =
println("take snapshot")
}
}
// then
"do the right thing" in
new WithBrowser(webDriver=WebDriverFactory(FIREFOX)) with TakeSnapshot {
browser.$( ".xyz1" ).text( "a" )
browser.$( ".xyz2" ).click()
browser.$( ".xyz3" ).getText must equalTo( "foo" )
browser.$( ".xyz1" ).text( "b" )
browser.$( ".xyz2" ).click()
browser.$( ".xyz3" ).getText must equalTo( "bar" )
}
When I execute it on a failing example I get a trace like
execute t // comes from a println in WithBrowser
take snapshot
quit browser // comes from a println in Browser
Related
I have an easy task to accomplish: read a password from a command line prompt without exposing it. I know that there is java.io.Console.readPassword, however, there are times when you cannot access console as if you are running your app from an IDE (such as IntelliJ).
I stumbled upon this Password Masking in the Java Programming Language tutorial, which looks nice, but I fail to implement it in Scala. So far my solution is:
class EraserThread() extends Runnable {
private var stop = false
override def run(): Unit = {
stop = true
while ( stop ) {
System.out.print("\010*")
try
Thread.sleep(1)
catch {
case ie: InterruptedException =>
ie.printStackTrace()
}
}
}
def stopMasking(): Unit = {
this.stop = false
}
}
val et = new EraserThread()
val mask = new Thread(et)
mask.start()
val password = StdIn.readLine("Password: ")
et.stopMasking()
When I start this snippet I get a continuos printing of asterisks on new lines. E.g.:
*
*
*
*
Is there any specific in Scala why this is not working? Or is there any better way to do this in Scala in general?
I have a variable param which has to be initialized at runtime.
Then, I have a part of the code which implements the following:
if (param has been initialized)
...do something...
else
print error and exit
What is the most idiomatic way to do this in Scala?
So far I have used Option[X] in this way:
var param : Option[TheType] = None
...
val param_value : TheType = x getOrElse {println("Error"); null}
But, since I have to return null it seems dirty.
How should I do it?
Simply map or foreach over it:
param.foreach { param_value =>
// Do everything you need to do with `param_value` here
} getOrElse sys.exit(3) # Param was empty, kill the program
You can also use the for comprehension style:
for {
param_value <- param
} yield yourOperation(param_value)
The upside of this is that if your calling code is expecting to do something with param_value as a return value from yourMethod you will encode the possibility of param_value not existing in your return type (it will be an Option[TheType] rather than a potentially null TheType.)
I might me wrong but it seems to me that the use of Future would fit with your problem: Instead of explicitly checking whether your required param_value has been initialized and finish the program if not, you could make your resource dependent code to execute when the resource has been rightly initialized:
val param: Future[TheType] = future {
INITIALIZATION CODE HERE
}
param onFailure {
case e => println("Error!");
}
param onSuccess {
case param_value: TheType => {
YOUR BUSINESS CODE HERE
}
}
I am new in Specs2. I read the specs2 documentation but it's kinda confusing. I don't know if it's possible or not.
So I have Specs2 test code roughly like this:
"DataServiceTest" should {
"InsertNewData" in {
val name = "some name here"
val description = "some description here"
// Assumed DataService.insertNewData method execute the insertion
// and returns "Data" model.
Data data = DataService.insertNewData(name, description)
// Checking of equality here
data.name === name
data.description === description
// Assumed the "Data" model has List[SubData] property "subData"
// and the code below is checking the List[SubData]
data.subData.foreach {
...
}
success
}
}
1. Is there a way to give message for these parts?
data.name === name
data.description === description
Something like "Checking data's name" in { data.name === name }. So the message will be shown on the output screen when the test is executed whether it's success or failed.
2. Is there a way to group the sub-code inside the "InsertNewData" by giving a text message like this:
"DataServiceTest" should {
"InsertNewData" in {
val name = "some name here"
val description = "some description here"
// Assumed DataService.insertNewData method execute the insertion
// and returns "Data" model.
Data data = DataService.insertNewData(name, description)
"Checking basic properties of Data" in {
// Checking of equality here
data.name === name
data.description === description
}
"Checking subData" in {
// Assumed the "Data" model has List[SubData] property "subData"
// and the code below is checking the subData
data.subData must have size(3)
data.subData.foreach {
...
}
}
success
}
}
UPDATE:
Based on one of answer here, I tried this:
"Checking of equality" ! e1
def e1 = {
data.name === name
data.description === description
failure
}
It didn't work as it should fail. But the test result is all passed.
UPDATE #2:
I did some experiment of nested in block:
"DataServiceTest" should {
"my test" in {
"hello test" in { // this block is not executed
"hello" !== "hello"
success
}
"world" === "world"
success
}
}
The result is success, but it should fail because of "hello" !== "hello". Looking from console screen, the is no "hello test" message, so it seems nested in block doesn't get executed.
UPDATE #3:
Based on edited answer by eric, I edited the code in Update #2:
"DataServiceTest" >> {
"my test" >> {
"hello test" >> { // this block is not executed
"hello" !== "hello"
success
}
"world" === "world"
success
}
}
Same result, the "hello test" nested block didn't get executed.
An easy way to create small examples based on one "ACT" call is to use a lazy val like this:
"DataServiceTest should" >> {
"InsertNewData" >> {
val name = "some name here"
val description = "some description here"
// Assumed DataService.insertNewData method execute the insertion
// and returns "Data" model.
lazy val data = DataService.insertNewData(name, description)
"name must be ok" >> {
data.name === name
}
"description must be ok" >> {
data.description === description
}
"subdata must be ok" >> {
data.subData.foreach {
...
}
success
}
}
You might find the Specs2 guides helpful:
https://etorreborre.github.io/specs2/guide/org.specs2.guide.Structure.html#Expectations
Look for "Expectations" in the guide.
Spec2 will just show that your tests will pass if the conditions are met. No message will be generated and usually this is sufficient. If your testsuite becomes large enough, then the positive messages will become numerous. You are more interested in failures anyways.
Spec2 does generate clear message by default and will use the variable name, the actual value and what it is supposed to be in general. But if that is not good enough, you can set a custom message. How this can be done can be seen in this stackoverflow answer
If you still want to generate the messages, you can use print statement and loggers. But I would advise you against it.
I would refactor to two different tests:
"DataServiceTest"
should {
"InsertNewData should have correct basic properties" in {
// Arrange
val name = "some name here"
val description = "some description here"
// Act
// Assumed DataService.insertNewData method execute the insertion
// and returns "Data" model.
Data data = DataService.insertNewData(name, description)
// Assert
// Checking of equality here
data.name === name
data.description === description
}
"InsertNewData should have correct subData" in {
// Arrange
val name = "some name here"
val description = "some description here"
// Act
// Assumed DataService.insertNewData method execute the insertion
// and returns "Data" model.
Data data = DataService.insertNewData(name, description)
// Assert
// Assumed the "Data" model has List[SubData] property "subData"
// and the code below is checking the
data.subData must have size(3)
data.subData.foreach {
...
}
}
}
I want to copy object properties to another object in a generic way (if a property exists on target object, I copy it from the source object).
My code works fine using ExpandoMetaClass, but I don't like the solution. Are there any other ways to do this?
class User {
String name = 'Arturo'
String city = 'Madrid'
Integer age = 27
}
class AdminUser {
String name
String city
Integer age
}
def copyProperties(source, target) {
target.properties.each { key, value ->
if (source.metaClass.hasProperty(source, key) && key != 'class' && key != 'metaClass') {
target.setProperty(key, source.metaClass.getProperty(source, key))
}
}
}
def (user, adminUser) = [new User(), new AdminUser()]
assert adminUser.name == null
assert adminUser.city == null
assert adminUser.age == null
copyProperties(user, adminUser)
assert adminUser.name == 'Arturo'
assert adminUser.city == 'Madrid'
assert adminUser.age == 27
I think the best and clear way is to use InvokerHelper.setProperties method
Example:
import groovy.transform.ToString
import org.codehaus.groovy.runtime.InvokerHelper
#ToString
class User {
String name = 'Arturo'
String city = 'Madrid'
Integer age = 27
}
#ToString
class AdminUser {
String name
String city
Integer age
}
def user = new User()
def adminUser = new AdminUser()
println "before: $user $adminUser"
InvokerHelper.setProperties(adminUser, user.properties)
println "after : $user $adminUser"
Output:
before: User(Arturo, Madrid, 27) AdminUser(null, null, null)
after : User(Arturo, Madrid, 27) AdminUser(Arturo, Madrid, 27)
Note: If you want more readability you can use category
use(InvokerHelper) {
adminUser.setProperties(user.properties)
}
I think your solution is quite good and is in the right track. At least I find it quite understandable.
A more succint version of that solution could be...
def copyProperties(source, target) {
source.properties.each { key, value ->
if (target.hasProperty(key) && !(key in ['class', 'metaClass']))
target[key] = value
}
}
... but it's not fundamentally different. I'm iterating over the source properties so I can then use the values to assign to the target :). It may be less robust than your original solution though, as I think it would break if the target object defines a getAt(String) method.
If you want to get fancy, you might do something like this:
def copyProperties(source, target) {
def (sProps, tProps) = [source, target]*.properties*.keySet()
def commonProps = sProps.intersect(tProps) - ['class', 'metaClass']
commonProps.each { target[it] = source[it] }
}
Basically, it first computes the common properties between the two objects and then copies them. It also works, but I think the first one is more straightforward and easier to understand :)
Sometimes less is more.
Another way is to do:
def copyProperties( source, target ) {
[source,target]*.getClass().declaredFields*.grep { !it.synthetic }.name.with { a, b ->
a.intersect( b ).each {
target."$it" = source."$it"
}
}
}
Which gets the common properties (that are not synthetic fields), and then assigns them to the target
You could also (using this method) do something like:
def user = new User()
def propCopy( src, clazz ) {
[src.getClass(), clazz].declaredFields*.grep { !it.synthetic }.name.with { a, b ->
clazz.newInstance().with { tgt ->
a.intersect( b ).each {
tgt[ it ] = src[ it ]
}
tgt
}
}
}
def admin = propCopy( user, AdminUser )
assert admin.name == 'Arturo'
assert admin.city == 'Madrid'
assert admin.age == 27
So you pass the method an object to copy the properties from, and the class of the returned object. The method then creates a new instance of this class (assuming a no-args constructor), sets the properties and returns it.
Edit 2
Assuming these are Groovy classes, you can invoke the Map constructor and set all the common properties like so:
def propCopy( src, clazz ) {
[src.getClass(), clazz].declaredFields*.grep { !it.synthetic }.name.with { a, b ->
clazz.metaClass.invokeConstructor( a.intersect( b ).collectEntries { [ (it):src[ it ] ] } )
}
}
Spring BeanUtils.copyProperties will work even if source/target classes are different types. http://docs.spring.io/autorepo/docs/spring/3.2.3.RELEASE/javadoc-api/org/springframework/beans/BeanUtils.html
I want my MainFrame to catch key events. I didn't find any key publisher already in it, so I'm going to write my own ... I have something like this:
class ImageView(image: ImageIcon, parent: UIElement = null) extends MainFrame {
object keys extends Publisher {
peer.addKeyListener(new KeyListener {
def keyPressed(e: java.awt.event.KeyEvent) {
publish(new KeyPressed(e))
}
def keyReleased(e: java.awt.event.KeyEvent) {
publish(new KeyReleased(e))
}
def keyTyped(e: java.awt.event.KeyEvent) {
publish(new KeyTyped(e))
}
})
}
listenTo(keys)
reactions += {
case KeyPressed(_, key,_,_) =>
if (key == Key.Escape) dispose
}
}
Anyway when I press any key, I get this exception:
Exception in thread "AWT-EventQueue-0" java.lang.ClassCastException: scala.swing.Frame$$anon$1 cannot be cast to javax.swing.JComponent
at scala.swing.event.KeyPressed.<init>(KeyEvent.scala:33)
at pip.gui.ImageView$keys$$anon$2.keyPressed(ImageView.scala:35)
at java.awt.Component.processKeyEvent(Component.java:6225)
at java.awt.Component.processEvent(Component.java:6044)
at java.awt.Container.processEvent(Container.java:2041)
at java.awt.Window.processEvent(Window.java:1836)
at java.awt.Component.dispatchEventImpl(Component.java:4630)
at java.awt.Container.dispatchEventImpl(Container.java:2099)
at java.awt.Window.dispatchEventImpl(Window.java:2478)
at java.awt.Component.dispatchEvent(Component.java:4460)
at java.awt.KeyboardFocusManager.redispatchEvent(KeyboardFocusManager.java:1850)
at java.awt.DefaultKeyboardFocusManager.dispatchKeyEvent(DefaultKeyboardFocusManager.java:712)
at java.awt.DefaultKeyboardFocusManager.preDispatchKeyEvent(DefaultKeyboardFocusManager.java:990)
at java.awt.DefaultKeyboardFocusManager.typeAheadAssertions(DefaultKeyboardFocusManager.java:855)
at
.
.
.
.
(continues long further)
I brought up this publisher code from Component.keys, so what is actually wrong here?
Thanks in advance,
Tony
This seems bad design in the library. Looking into KeyEvent.scala, there's all kinds of casting to JComponent going on, and JFrame is a subclass of java.awt.Component but not JComponent, so it should be impossible to call listenTo(keys).
What you want is to listen to the top-most component in the frame's contents. For instance:
import scala.swing._; import event._
import javax.swing._
class ImageView(image: ImageIcon, parent: UIElement = null) extends MainFrame {
val b = new BorderPanel {
listenTo( keys )
reactions += {
case KeyPressed(_, key,_,_) =>
println( "PRESSED : " + key )
if (key == Key.Escape) dispose
}
}
contents = b
}
val w = new ImageView( null )
w.peer.setSize( 200, 200 )
w.visible = true
w.b.requestFocus
the requestFocus is essential because the panel doesn't request the focus by itself even if you click on it, so otherwise it wouldn't receive key events.