How to initialize shared variables before parallel test in scalatest - scala

I have scalatest codes like following:
class myTest extends FlatSpec with ParallelTestExecution {
val testSuiteId: String = GenerateSomeRandomId()
it should "print test id" in {
println(testSuiteId)
}
it should "print test id again" in {
println(testSuiteId)
}
}
The two tests cannot print the testSuiteId I generate before them. Instead they regenerate the ID and print it. I understand that because of ParallelTestExecution which extends OneInstancePerTest, each test here runs on its own instance and have a copy of the variable "testSuiteId".
But I do want a fixed Id for this test suite and each test case in this suite have access to this fixed it without modifying it. I tried to create the fixed id in BeforeAll{ } but still it didn't work.
How should I achieve what I want?

One way to work around it would be to put the shared state in some sort of external object:
object SuiteId {
lazy val id: String = GenerateSomeRandomId()
}
Admittedly this is very much a hack, and I wouldn't be surprised if scalatest has a way to handle this built-in which I am unaware of.

Related

Dynamicaly Created Tests sbt

I'm trying to dynamically run some basic tests in the following way (this is a pseudo code of my test, my actual tests are a bit more complicated):
class ExampleTest extends AnyWordSpec {
def runTests() = {
for( n <- 1 until 10){
testNumber(n)
}
}
def testNumber(n: Int) = {
"testNumber" when {
s"gets the number ${n}" should {
"fail if the number is different than 0" {
assert(n == 0)
}
}
}
}
runTests()
}
When I try to run my tests in IntelliJ all the tests run as expected. But when using sbt tests It says that all my tests passed even though non of my tests actually got executed (I get the message "1 tests suite executed. 0 tests where executed").
How can I fix this? Is there any other simple way to dynamically create tests in scala?)
As mentioned in a comment, I'm not sure what the problem with sbt is.
Another way you can try to create test dynamically is using property-based testing.
One possible way is using table-driven property checks, as in the following example (which you can see in action here on Scastie):
import org.scalatest.wordspec.AnyWordSpec
import org.scalatest.prop.TableDrivenPropertyChecks._
class ExampleTest extends AnyWordSpec {
private val values = Table("n", (1 to 10): _*)
"testNumber" when {
forAll(values) { n =>
s"gets the number ${n}" should {
"fail if the number is different than 0" in {
assert(n == 0)
}
}
}
}
}
Of course all these tests are going to fail. ;-)
Links to the ScalaTest documentation about the topic:
property-based testing
table-driven property checks
generator-driven property checks (especially useful to test a lot of cases within the same case)

How to get Test Case name in Katalon Studio

I am trying to take a screenshot of every Test Case and have it exported to a screenshot directory with its name.
I am using:
testName = RunConfiguration.getExecutionSourceName().toString()
but this only contains the name of the Test Suite and NOT the Test Case name.
WebUI.takeScreenshot('path'+testName+'.png')
How would I reference the Test Case name and not the Test Suite name?
Thank you.
EDIT: The code I am taking a screenshot of currently lives in the "TearDownTestCase" method located in Test Suites.
Okay so I figured it out with the help of #Mate Mrse. Running the .getExecutionSource() method would return me the Test Suite name when running a Test Suite. However I needed to return the Test Case name.
I first created a Test Listener and added to the '#BeforeTestCase':
class TestCaseName {
#BeforeTestCase
def sampleBeforeTestCase(TestCaseContext testCaseContext) {
String testCaseId = testCaseContext.getTestCaseId()
}
}
This returns the path:
../Katalon Studio/Test Cases/Test Case Name
Then I've used the .substring() method to store the Test Case Name as a string
class TestCaseName {
#BeforeTestCase
def sampleBeforeTestCase(TestCaseContext testCaseContext) {
String testCaseId = testCaseContext.getTestCaseId()
GlobalVariable.testCaseName = testCaseId.substring((testCaseId.lastIndexOf("/").toInteger()) + 1)
}
}
Thank you #Mate Mrse
You can use RunConfiguration.getExecutionSource() to get the full path to the test case being run.
And then you can do with that whatever you want. For example, to get the test case name you might do something like
RunConfiguration.getExecutionSource().toString().substring(RunConfiguration.getExecutionSource().toString().lastIndexOf("\\")+1)
Explanation:
The .getExecutionSource() method will give you a full path to your test case, something like C:\users\user.name\Katalon Studio\Test Cases\Test Case Name.tc (you might have something different).
Since you want only the last part, you can use Groovy to cut this string to something you like. So, I cut the string at the place of the last \ (that is what the lastIndexOf is doing) just before the Test Case Name.tc (+1 because I want to cut the backslash as well).
Then the .substring() method will give me just what is leftover after the cut.

Scala - ScalaTest: simulate input while testing

I've a application that's run on top of terminal.
This App uses only Scala and SBT and I'm testing it using ScalaTest.
I want to test all components like a integration test, running the app, but, for that, I want to simulate the user sending values via standard input using something like a robot. Most important of all, when I call readLine or readInt, I want to send differents values while testing.
Thanks in advance!
Edit 1
So, I've this code. It basically prints the options for the user. I want, for example, to send 1, and then 3,4, to create a new Cell and check my CellArray to check if a new cell was really created in that position.
do {
println("Select one of the options: \n \n");
println("[1] Make a cell alive");
println("[2] Next generation");
println("[3] Halt");
print("\n \n Option: ");
option = parseOption(readLine)
}while(option == 0)
option match {
case MAKE_CELL_ALIVE => makeCellAlive
case NEXT_GENERATION => nextGeneration
case HALT => halt
}
The general approach will be something along these lines.
// This is the class containing the logic you want to test
class MyInputThing {
def readInput() = readLine
def thingIWantToTest = {
val input = readInput
doStuffWithInput(input)
}
}
// This test class returns a value representing something you want to verify.
class TestMyInputThing extends MyInputThing {
override def readInput = "123"
}
Then, in your test, use TestMyInputThing.thingIWantToTest() and validate the response. You can also pull out readInput into a trait, parameterise the creation of TestMyInputThing, etc, in order to clean this up. I would also recommend looking into ScalaCheck so you don't need to handcode test scenarios.

Couldn't run individual scala test in Intellij

I came across an issue earlier where I couldn't run an indivdual scala test, it would always try to run all of them even if I set the configuration to just be running one test. Does anyone know of any settings/configuration I can change to get it to run?
class MyTest extends PlaySpec {
val setTo = new AfterWord("set to")
"Setting" when setTo {
"value a" in {
//test stuff
}
"value b" in {
//test stuff
}
}
Turns out it was the use of the AfterWord that was messing up my test, once I removed it the tests ran fine. I'm not sure why they're incompatible but if you want to run individual tests, don't use an AfterWord.

How to test methods based on Salat with ScalaTest

I'm writing a web-app using Play 2, Salat (for mongoDB bindin). I would like to test some methods, in the Lesson Model (for instance test the fact that I retrieve the right lesson by id). The problem is that I don't want to pollute my current DB with dummy lessons. How can I use a fake DB using Salat and Scala Test ? Here is one of my test file. It creates two lessons, and insert it into the DB, and it runs some tests on it.
LessonSpec extends FlatSpec with ShouldMatchers {
object FakeApp extends FakeApplication()
val newLesson1 = Lesson(
title = "lesson1",
level = 5,
explanations = "expl1",
questions = Seq.empty)
LessonDAO.insert(newLesson1)
val newLesson2 = Lesson(
title = "lesson2",
level = 5,
explanations = "expl2",
questions = Seq.empty)
LessonDAO.insert(newLesson2)
"Lesson Model" should "be retrieved by level" in {
running(FakeApp) {
assert(Lesson.findByLevel(5).size === 2)
}
}
it should "be of size 0 if no lesson of the level is found" in {
running(FakeApp) {
Lesson.findByLevel(4) should be(Nil)
}
}
it should "be retrieved by title" in {
running(FakeApp) {
Lesson.findOneByTitle("lesson1") should be(Some(Lesson("lesson1", 5, "expl1", List())))
}
}
}
I searched on the web but i can't find a good link or project that use Salat and ScalaTest.
Salat developer here. My recommendation would be to have a separate test only database. You can populate it with test data to put your test database in a known state - see the casbah tests for how to do this - and then test against it however you like, clearing out collections as necessary.
I use specs2, not scalatest, but the principle is the same - see the source code for the Salat tests.
Here's a good test to get you started:
https://github.com/novus/salat/blob/master/salat-core/src/test/scala/com/novus/salat/test/dao/SalatDAOSpec.scala
Note that in my base spec I clear out my test database - this gets run before each spec:
trait SalatSpec extends Specification with Logging {
override def is =
Step {
// log.info("beforeSpec: registering BSON conversion helpers")
com.mongodb.casbah.commons.conversions.scala.RegisterConversionHelpers()
com.mongodb.casbah.commons.conversions.scala.RegisterJodaTimeConversionHelpers()
} ^
super.is ^
Step {
// log.info("afterSpec: dropping test MongoDB '%s'".format(SalatSpecDb))
MongoConnection().dropDatabase(SalatSpecDb)
}
And then in SalatDAOSpec, I run my tests inside scopes which create, populate and/or clear out individual collections so that the tests can run in an expected state. One hitch: if you run your tests concurrently on the same collection, they may fail due to unexpected state. The solution is either to run your tests in isolated special purpose collections, or to force your tests to run in series so that operations on a single collection don't step on each other as different test cases modify the collection.
If you post to the Scalatest mailing list (http://groups.google.com/group/scalatest-users), I'm sure someone can recommend the correct way to set this up.
In my applications, I use a parameter in application.conf to specify the Mongo database name. When initializing my FakeApplication, I override that parameter so that my unit tests can use a real Mongo instance but do not see any of my production data.
Glossing over a few details specific to my application, my tests look something like this:
// wipe any existing data
db.collectionNames.foreach { colName =>
if (colName != "system.indexes") db.getCollection(colName).drop
}
app = FakeApplication(additionalConfiguration = Map("mongo.db.name" -> "unit-test"))