Spek parameterized tests - unit-testing

I'm trying to write a single test from about 8 hours... The problem is really strange behavior (for me) in Spek. Sometimes it executes, sometimes not. I had an error "Test class cannot have two constructors" without any reason. When i deleted class DriverTest(val filePath: String, val expectedTextResult: String) and then put it again, it worked... Anyway, what I'm trying to do is parameterized test:
#RunWith(JUnitPlatform::class)
class ChromeDriverConfigurationTest : Spek
({
class DriverTest(val filePath: String, val expectedTextResult: String)
given("Chrome Driver") {
val chromeDriver: ChromeDriver by lazy { setupChromeDriverForTest() }
afterGroup { deleteChromeDriver(chromeDriver) }
listOf(
DriverTest(filePath = "js/js.html", expectedTextResult = "Text from JS!"),
DriverTest(filePath = "jQuery/jQuery.html", expectedTextResult = "I come from jQuery!"),
DriverTest(filePath = "angularv1/angularv1.html", expectedTextResult = "Hello from Angular v1!"),
DriverTest(filePath = "reactJS/index.html", expectedTextResult = "Hello from reactJS!")
).forEach { driverTest ->
println("BBBBBBBBBBBBBBBBBBBBBB")
val path = ChromeDriverConfigurationTest::class.java.getResource(driverTest.filePath).path
chromeDriver.get("file://$path")
it("should extract test") {
println("AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA")
val text = chromeDriver.findElement(By.id("test")).text
assert(text == driverTest.expectedTextResult)
}
}
}
})
In this case, I dont see any "AAAAAAAAAAAAAA..", but I see "BBBBBBBB" 4 times. It loks like, it section doesn't run. Alright, maybe there is something wrong with chromeDriver.get, lets comment it (rest stays same)
//val path = ChromeDriverConfigurationTest::class.java.getResource(driverTest.filePath).path
//chromeDriver.get("file://$path")
Now I get...
BBBBBBBBBBBBBBBBBBBBBB
BBBBBBBBBBBBBBBBBBBBBB
BBBBBBBBBBBBBBBBBBBBBB
BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB
BBBBBBBBBBBBBBBBBBBBBB
BBBBBBBBBBBBBBBBBBBBBB
BBBBBBBBBBBBBBBBBBBBBB
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
he? whats going on. Alright, lets move context group inside for each like I saw in many tutorials:
#RunWith(JUnitPlatform::class)
class ChromeDriverConfigurationTest : Spek
({
class DriverTest(val filePath: String, val expectedTextResult: String)
listOf(
DriverTest(filePath = "js/js.html", expectedTextResult = "Text from JS!"),
DriverTest(filePath = "jQuery/jQuery.html", expectedTextResult = "I come from jQuery!"),
DriverTest(filePath = "angularv1/angularv1.html", expectedTextResult = "Hello from Angular v1!"),
DriverTest(filePath = "reactJS/index.html", expectedTextResult = "Hello from reactJS!")
).forEach { driverTest ->
given("Chrome Driver") {
val chromeDriver: ChromeDriver by lazy { setupChromeDriverForTest() }
afterGroup { deleteChromeDriver(chromeDriver) }
println("BBBBBBBBBBBBBBBBBBBBBB")
val path = ChromeDriverConfigurationTest::class.java.getResource(driverTest.filePath).path
chromeDriver.get("file://$path")
it("should extract test") {
println("AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA")
val text = chromeDriver.findElement(By.id("test")).text
assert(text == driverTest.expectedTextResult)
}
}
}
})
Surprise again:
BBBBBBBBBBBBBBBBBBBBBB
BBBBBBBBBBBBBBBBBBBBBB
BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB
BBBBBBBBBBBBBBBBBBBBBB
BBBBBBBBBBBBBBBBBBBBBB
BBBBBBBBBBBBBBBBBBBBBB
Okay, just leave these "readability", and make it work... Lets put everything to it section.
#RunWith(JUnitPlatform::class)
class ChromeDriverConfigurationTest : Spek
({
class DriverTest(val filePath: String, val expectedTextResult: String)
listOf(
DriverTest(filePath = "js/js.html", expectedTextResult = "Text from JS!"),
DriverTest(filePath = "jQuery/jQuery.html", expectedTextResult = "I come from jQuery!"),
DriverTest(filePath = "angularv1/angularv1.html", expectedTextResult = "Hello from Angular v1!"),
DriverTest(filePath = "reactJS/index.html", expectedTextResult = "Hello from reactJS!")
).forEach { driverTest ->
given("Chrome Driver") {
it("should extract test") {
val chromeDriver: ChromeDriver by lazy { setupChromeDriverForTest() }
afterGroup { deleteChromeDriver(chromeDriver) }
println("BBBBBBBBBBBBBBBBBBBBBB")
val path = ChromeDriverConfigurationTest::class.java.getResource(driverTest.filePath).path
chromeDriver.get("file://$path")
println("AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA")
val text = chromeDriver.findElement(By.id("test")).text
assert(text == driverTest.expectedTextResult)
}
}
}
})
Ohh great it works! But wait a second..., it executes only 1 test, I mean only for first element in list. Hę? Could someone explain me please this behavior? Also maybe you know some other alternatives to Spek? I would write my tests in Kotlin. But with Spek it looks almost impossible

Related

When unit testing my ViewModel, list always returns empty

I'm trying to learn unit testing, I have my code factored into an MVVM(i) architecture, but when I run my testParseToList() test function, it always comes back with an empty list and I can't figure out why. I fear it may have something to do with the i part of the MVVM(i) and whether or not I'm correctly mocking my viewmodel. I'm starting with my most simple viewmodel in hopes to get a grasp of the concepts before moving onto my more complex ones.
OfflineViewModelUnitTest.kt
#RunWith(JUnit4::class)
class OfflineViewModelUnitTest {
#get:Rule
val rule = InstantTaskExecutorRule()
#Mock
var offlineViewModel: OfflineViewModel = OfflineViewModel(OfflineInteractorImpl())
#Before
fun setup() {
MockitoAnnotations.initMocks(this)
DaggerOfflineViewModelComponent.builder()
.offlineInteractorImplModule(OfflineInteractorImplModule())
.build()
.inject(offlineViewModel)
// this.offlineViewModel = OfflineViewModel(OfflineInteractorImpl())
}
#Test
fun testParseToList() {
val test = offlineViewModel.parseTextToList("dried bonito extract,\n" +
" ketchup,\n" +
" millet,\n" +
" corn & wheat protein")
val a = "dried bonito extract"
val b = "ketchup"
val c = "millet"
val d = "corn & wheat protein"
val expectedResult = listOf(a, b, c, d)
assertEquals(expectedResult, test)
}
}
OfflineViewModel.kt
class OfflineViewModel(private val offlineInteractor: OfflineInteractor): ViewModel() {
init {
DaggerOfflineViewModelComponent.builder()
.offlineInteractorImplModule(OfflineInteractorImplModule())
.build()
.inject(this)
}
fun parseTextToList(firebaseVisionTextString: String): MutableList<String> {
Log.d("here it is", firebaseVisionTextString)
return offlineInteractor.parseTextToList(firebaseVisionTextString)
}
fun readCsvFromAssetFolder(inputStream: InputStream): List<String>{
return offlineInteractor.readCsvFromAssetFolder(inputStream)
}
}
OfflineInteractorImpl.kt
class OfflineInteractorImpl: OfflineInteractor {
override fun parseTextToList(firebaseVisionTextString: String): MutableList<String> {
val ingredientsList: MutableList<String> = firebaseVisionTextString.split(",").map { it.trim() }.toMutableList()
return ingredientsList
}
override fun readCsvFromAssetFolder(inputStream: InputStream): List<String> {
val csvLine: ArrayList<String> = ArrayList()
var content: Array<String>?
try
{
val br = BufferedReader(InputStreamReader(inputStream))
for (line in br.lines())
{
content = line.split((",").toRegex()).dropLastWhile{ it.isEmpty() }.toTypedArray()
csvLine.add(content[0].substringBefore(";"))
}
br.close()
}
catch (e: IOException) {
e.printStackTrace()
}
return csvLine
}
}
Test Results
java.lang.AssertionError:
Expected :[dried bonito extract, ketchup, millet, corn & wheat protein]
Actual :[]
Like second said, since you mocked offlineViewModel it is going to return an empty string, unless you define something for it to return using when().
Source: https://github.com/mockito/mockito/wiki/FAQ#what-values-do-mocks-return-by-default

Scala Regex pattern matching issue when using |

This is my example code.
object Patterns {
val workingPattern = """^thisworks[\w]+""".r
val problemPattern = """^(fail|error|bs|meh)[\w]+""".r
}
object TestMaker {
var works = scala.collection.mutable.Set[String]()
var needsWork = scala.collection.mutable.Set[String]()
var junk = scala.collection.mutable.Set[String]()
def add(someInput: String) = someInput match {
case Patterns.workingPattern() => works.update(someInput, true)
case Patterns.problemPattern() => needsWork.update(someInput, true)
case _ => junk.update(someInput, true)
}
}
When I call TestMaker.add("thisworks1234"), the string "thisworks1234" gets inserted into TestMaker's works set. It works as expected.
When I call TestMaker.add("this_is_just_junk"), the string "this_is_just_junk" gets inserted into the junk set - also as expected.
Here's the problem. When I call TestMaker.add("fail1234"), that string will also be inserted into the junk set. It should however be inserted into the needsWork set.
Where's my mistake?
You should use a non-capturing group with the second regex:
val problemPattern = """^(?:fail|error|bs|meh)[\w]+""".r
^^^
This is required because you are not referencing the captured value in your case.
Note that you can still use capturing groups within your patterns to ignore them later while matching with _*:
case Patterns.workingPattern(_*) => works.update(someInput, true)
case Patterns.problemPattern(_*) => needsWork.update(someInput, true)
case _ => junk.update(someInput, true)
See the IDEONE demo:
object Main extends App {
TestMaker.add("this_is_just_junk")
TestMaker.add("fail1234")
println(TestMaker.needsWork) // => Set(fail1234)
println(TestMaker.junk) // => Set(this_is_just_junk)
}
object Patterns {
val workingPattern = """^thisworks[\w]+""".r
val problemPattern = """^(fail|error|bs|meh)[\w]+""".r
}
object TestMaker {
var works = scala.collection.mutable.Set[String]()
var needsWork = scala.collection.mutable.Set[String]()
var junk = scala.collection.mutable.Set[String]()
def add(someInput: String) = someInput match {
case Patterns.workingPattern(_*) => works.update(someInput, true)
case Patterns.problemPattern(_*) => needsWork.update(someInput, true)
case _ => junk.update(someInput, true)
}
}

Get object of case class from regex match

i'm working on scraping data from a webpage with scala regex-es, but i encountered problem with parsing result to object of some case class-es.
In following snippet i managed to scrape all the data, but i have no clue how to parse 3 elements from an iterator. I thought about something like:
val a :: b :: c :: _ = result.group(0).iDontKnowWha
Any ideas what can i do?
import model.FuneralSchedule
import play.api.libs.json.Json
import scala.io.Source
var date = "2015-05-05"
val source = Source.fromURL("http://zck.krakow.pl/?pageId=16&date=" + date).mkString
val regex = "(?s)<table>.+?(Cmentarz.+?)<.+?</table>".r
var thing: List[FuneralSchedule] = List()
var jsonFeed: List[Funeral] = List()
val regMatcher = "("
case class Funeral(hour: String, who: String, age: String) {
override def toString: String = {
"Cos"
}
}
//implicit val format = Json.format[Funeral]
val out = regex.findAllIn(source).matchData foreach { table =>
thing ::= FuneralSchedule(table.group(1), clearStrings(table.group(0)))
"""<tr\s?>.+?</\s?tr>""".r.findAllIn(clearStrings(table.group(0))).matchData foreach { tr =>
//TODO: Naprawic bo szlak trafia wydajnosc
val temp = """<td\s?>.+?</\s?td>""".r.findAllIn(tr.group(0)).matchData.foreach {
elem => println(elem)
}
//println(Json.toJson(thingy))
}
println("Koniec tabeli")
}
thing
//Json.toJson(jsonFeed)
println(removeMarkers("<td > <td> Marian Debil </ td>"))
def removeMarkers(s: String) = {
s.replaceAll( """(</?\s?td\s?>)""", "")
}
def clearStrings(s: String) = {
val regex = "((class=\".+?\")|(id=\".+?\")|(style=\".+?\")|(\\n))"
s.replaceAll(regex, "")
}
One way of doing it would be converting it to a Stream and matching it using stream's operators like this:
val a #:: b #:: c #:: _ = """([a-z]){1}""".r.findAllIn("a b c").toStream
then a, b and c is what you're looking for

Scala - Loop + format

Hey guys I´m completely new to Scala and need some Help.My goal is to write a programm wich takes a List and a Command as Input.Then it should either return the list, the average Length of the list or the"longest" Entry. Furthermore it shuld ask over and over again for input, and this is what I dont know how to write. Also I have some problems with the formatting ("%.1f"). Does somebody know how to solve these Problems. Thank you very much. This is my code:
import scala.io.Source
var input = readLine("Enter a List")
val cmd = readLine("Entera command")
input=input.replace(" ","")
var input2=input.split(",").toList
def exercise() {
cmd match {
case "maxLength" => println(getMaxLength(input2))
case "list" => getList(input2)
case "averageLength" => println("%.1f".format(getAverageLeng(input2)))
case "exit" => sys.exit()
case _ => println("unknown command")
}
}
def getMaxLength(list:List[String]): String = {
list match {
case Nil => return ""
case _ => return list.fold("")((l, v) => if (l.length > v.length) l else v)
}
}
def getAverageLeng(list:List[String]): Number = {
list match {
case Nil => return 0.0
case _ => return list.map(_.length()).sum.asInstanceOf[Int] / list.length
}
}
def getList(list:List[String]):Unit = {
list match {
case Nil => return
case _ => list foreach println
}
}
exercise()
}
You need to put
var input = readLine("Enter a List")
val cmd = readLine("Entera command")
input=input.replace(" ","")
var input2=input.split(",").toList
part into exercise() function and call it recursively.
This is for asking until You type exit
The second problem is getAverageLeng signature it should return Double not Number,
and change sum.asInstanceOf[Int] to sum.asInstanceOf[Double] in this function.

Scala - replaceAllIn

First off, I'm new to Scala.
I'm trying to make a template parser in Scala (similar to Smarty (PHP)). It needs to search through the document, replacing anything inside "{{ }}" tags, with anything provided in the HashMap.
I'm currently stuck here:
import scala.collection.mutable.HashMap
import scala.io.Source
class Template(filename: String, vars: HashMap[Symbol, Any]) {
def parse() = {
var contents = Source.fromFile(filename, "ASCII").mkString
var rule = """\{\{(.*)\}\}""".r
//for(rule(v) <- rule findAllIn contents) {
// yield v
//}
//rule.replaceAllIn(contents, )
}
}
var t = new Template("FILENAME", new HashMap[Symbol, Any])
println(t.parse)
The part's that I've commented are things that I've thought about doing.
Thanks
I've come a little further...
import scala.collection.mutable.HashMap
import scala.io.Source
import java.util.regex.Pattern
import java.util.regex.Matcher
class Template(filename: String, vars: HashMap[Symbol, Any]) {
def findAndReplace(m: Matcher)(callback: String => String):String = {
val sb = new StringBuffer
while (m.find) {
m.appendReplacement(sb, callback(m.group(1)))
}
m.appendTail(sb)
sb.toString
}
def parse() = {
var contents = Source.fromFile(filename, "ASCII").mkString
val m = Pattern.compile("""\{\{(.*)\}\}""").matcher(contents)
findAndReplace(m){ x => x }
}
}
var t = new Template("FILENAME.html", new HashMap[Symbol, Any])
println(t.parse)
At the moment it just currently adds whatever was inside of the tag, back into the document. I'm wondering if there is an easier way of doing a find-and-replace style regexp in Scala?
I'd do it like this (String as key instead of Symbol):
var s : String = input // line, whatever
val regexp = """pattern""".r
while(regexp findFirstIn s != None) {
s = regexp replaceFirstIn (s, vars(regexp.findFirstIn(s).get))
}
If you prefer not using var, go recursive instead of using while. And, of course, a stringbuilder would be more efficient. In that case, I might do the following:
val regexp = """^(.*?)(?:{{(pattern)}})?""".r
for(subs <- regexp findAllIn s)
subs match {
case regexp(prefix, var) => sb.append(prefix); if (var != null) sb.append("{{"+vars(var)+"}}")
case _ => error("Shouldn't happen")
}
That way you keep appending the non-changing part, followed by the next part to be replaced.
There is a flavor of replaceAllIn in util.matching.Regex that accepts a replacer callback. A short example:
import util.matching.Regex
def replaceVars(r: Regex)(getVar: String => String) = {
def replacement(m: Regex.Match) = {
import java.util.regex.Matcher
require(m.groupCount == 1)
Matcher.quoteReplacement( getVar(m group 1) )
}
(s: String) => r.replaceAllIn(s, replacement _)
}
This is how we would use it:
val r = """\{\{([^{}]+)\}\}""".r
val m = Map("FILENAME" -> "aaa.txt",
"ENCODING" -> "UTF-8")
val template = replaceVars(r)( m.withDefaultValue("UNKNOWN") )
println( template("""whatever input contains {{FILENAME}} and
unknown key {{NOVAL}} and {{FILENAME}} again,
and {{ENCODING}}""") )
Note Matcher.quoteReplacement escapes $ characters in the replacement string. Otherwise you may get java.lang.IllegalArgumentException: Illegal group reference, replaceAll and dollar signs. See the blog post on why this may happen.
Here is also interesting way how to do the same using functions compose:
val Regexp = """\{\{([^{}]+)\}\}""".r
val map = Map("VARIABLE1" -> "VALUE1", "VARIABLE2" -> "VALUE2", "VARIABLE3" -> "VALUE3")
val incomingData = "I'm {{VARIABLE1}}. I'm {{VARIABLE2}}. And I'm {{VARIABLE3}}. And also {{VARIABLE1}}"
def replace(incoming: String) = {
def replace(what: String, `with`: String)(where: String) = where.replace(what, `with`)
val composedReplace = Regexp.findAllMatchIn(incoming).map { m => replace(m.matched, map(m.group(1)))(_) }.reduceLeftOption((lf, rf) => lf compose rf).getOrElse(identity[String](_))
composedReplace(incomingData)
}
println(replace(incomingData))
//OUTPUT: I'm VALUE1. I'm VALUE2. And I'm VALUE3. And also VALUE1