SBT cannot resolve class declared in src/main/scala in a src/test/scala test class - scala

I am trying to make my own custom CSV reader. I am using IntelliJ IDEA 14 with sbt and specs2 test framework.
The class I declared in src/main is as follows:
import java.io.FileInputStream
import scala.io.Source
class CSVStream(filePath:String) {
val csvStream = Source.fromInputStream(new FileInputStream(filePath)).getLines()
val headers = csvStream.next().split("\\,", -1)
}
The content of the test file in src/test is as follows:
import org.specs2.mutable._
object CSVStreamSpec {
val csvSourcePath = getClass.getResource("/csv_source.csv").getPath
}
class CSVStreamSpec extends Specification {
import CSVStreamLib.CSVStreamSpec._
"The CSV Stream reader" should {
"Extract the header" in {
val csvSource = CSVStream(csvSourcePath)
}
}
}
The build.sbt file contains the following:
name := "csvStreamLib"
version := "1.0"
scalaVersion := "2.11.4"
libraryDependencies ++= Seq("org.specs2" %% "specs2-core" % "2.4.15" % "test")
parallelExecution in Test := false
The error I am getting when I type test is as follows:
[error] /Users/raiyan/IdeaProjects/csvStreamLib/src/test/scala/csvStreamSpec.scala:18: not found: value CSVStream
[error] val csvSource = CSVStream(csvSourcePath)
[error] ^
[error] one error found
[error] (test:compile) Compilation failed
[error] Total time: 23 s, completed 30-Dec-2014 07:44:46
How do I make the CSVStream class accessible to the CSVStreamSpec class in the test file?
Update:
I tried it with sbt in the command line. The result is the same.

You forgot the new keyword. Without it, the compiler looks for the companion object named CSVStream, not the class. Since there is none, it complains. Add new and it'll work.

Related

Issue in testing using scalatest

I just set up a new scala project with sbt in IntelliJ, and wrote the following basic class:
Person.scala:
package learning.functional
case class Person(
name: String
)
Main.scala:
package learning.functional
import learning.functional.person
object Main{
val p = Person("John")
}
PersonTest.scala:
import learning.functional.Person
import org.scalatest.FunSuite
class PersonTest extends FunSuite {
test("test person") {
val p = Person("John")
assert(p.name == "John")
}
}
When I try to run sbt test, it throws the following error:
## Exception when compiling 1 sources to /Users/johndooley/Desktop/Scala/scala-learning/target/scala-2.13/test-classes
[error] java.lang.AssertionError: assertion failed:
[error] unexpected value engine in trait FunSuite final <expandedname> private[this]
[error] while compiling: /Users/johndooley/Desktop/Scala/scala-learning/src/test/scala/PersonTest.scala
What could be the reason for this? My build.sbt file:
ThisBuild / scalaVersion := "2.13.10"
libraryDependencies += "org.scalatest" % "scalatest_2.10" % "1.9.1"
lazy val root = (project in file("."))
.settings(
name := "scala-learning"
)
Project structure:
I have tried invalidating cache and restarting, doing clean, update, compile, but nothing works.
I solved this by modifying my dependency to the following:
libraryDependencies += "org.scalatest" %% "scalatest" % "3.2.14"
and completely reloading the sbt shell

Can't find SttpBackends + "Error occurred in an application involving default arguments."

I'm trying to create a extremely simple Telegram bot in Scala using bot4s. I'm pretty much following the example there. Here's the code:
package info.jjmerelo.BoBot
import cats.instances.future._
import cats.syntax.functor._
import com.bot4s.telegram.api.RequestHandler
import com.bot4s.telegram.api.declarative.Commands
import com.bot4s.telegram.clients.{FutureSttpClient, ScalajHttpClient}
import com.bot4s.telegram.future.{Polling, TelegramBot}
import scala.util.Try
import scala.concurrent.Future
import com.typesafe.scalalogging.Logger
object BoBot extends TelegramBot
with Polling
with Commands[Future] {
implicit val backend = SttpBackends.default
def token = sys.env("BOBOT_TOKEN")
override val client: RequestHandler[Future] = new FutureSttpClient(token)
val log = Logger("BoBot")
// val lines = scala.io.Source.fromFile("hitos.json").mkString
// val hitos = JSON.parseFull( lines )
// val solo_hitos = hitos.getOrElse( hitos )
onCommand("hey") { implicit msg =>
log.info("Hello")
reply("Conseguí que funcionara").void
}
}
And here's the build.sbt
name := "bobot"
version := "0.0.1"
organization := "info.jjmerelo"
libraryDependencies += "com.bot4s" %% "telegram-core" % "4.4.0-RC2"
val circeVersion = "0.12.3"
libraryDependencies ++= Seq(
"io.circe" %% "circe-core",
"io.circe" %% "circe-generic",
"io.circe" %% "circe-parser"
).map(_ % circeVersion)
libraryDependencies += "com.typesafe.scala-logging" %% "scala-logging" % "3.9.2"
retrieveManaged := true
Circe is for later
Anyway, I managed to compile most of it, but I still get these two errors:
[info] compiling 2 Scala sources to /home/jmerelo/Asignaturas/cloud-computing/BoBot/target/scala-2.12/classes ...
[error] /home/jmerelo/Asignaturas/cloud-computing/BoBot/src/main/scala/info/jjmerelo/BoBot.scala:21:26: not found: value SttpBackends
[error] implicit val backend = SttpBackends.default
[error] ^
[error] /home/jmerelo/Asignaturas/cloud-computing/BoBot/src/main/scala/info/jjmerelo/BoBot.scala:23:49: could not find implicit value for parameter backend: com.softwaremill.sttp.SttpBackend[scala.concurrent.Future,Nothing]
[error] Error occurred in an application involving default arguments.
[error] override val client: RequestHandler[Future] = new FutureSttpClient(token)
[error] ^
[error] two errors found
[error] (Compile / compileIncremental) Compilation failed
[error] Total time: 5 s, completed 11 nov. 2020 8:19:38
I can't figure out either of the two. SttpBackends is missing, that's clear, but there's nothing in the example that indicates it's needed, or, for that matter, what library should be included. The second one about the default arguments I simply can't figure it out, even if I define token as String or if I change def to val. Any idea?
Your error messages is associated with each other.
First error tells us that compiler couldn't find object SttpBackends which has field of SttpBackend.
The second one tells us that compiler couldn't find implicit backend: SttpBackend for constructing FutureSttpClient. It requires two implicits: SttpBackend and ExecutionContext.
class FutureSttpClient(token : _root_.scala.Predef.String,
telegramHost : _root_.scala.Predef.String = { /* compiled code */ })
(implicit backend : com.softwaremill.sttp.SttpBackend[scala.concurrent.Future, scala.Nothing],
ec : scala.concurrent.ExecutionContext)
extends com.bot4s.telegram.clients.SttpClient[scala.concurrent.Future] {...}
You can create it by yourself as in bot4s examples.
If you will try to find SttpBackends object in bot4s library you would found this code in bot4s examples:
import com.softwaremill.sttp.okhttp._
object SttpBackends {
val default: SttpBackend[Future, Nothing] = OkHttpFutureBackend()
}
add this object to your project to make it compilable.

value wholeTextFiles is not a member of org.apache.spark.SparkContext

I have a Scala code like below :-
import org.apache.spark.SparkContext
import org.apache.spark.SparkContext._
import org.apache.spark.SparkConf
import org.apache.spark._
object RecipeIO {
val sc = new SparkContext(new SparkConf().setAppName("Recipe_Extraction"))
def read(INPUT_PATH: String): org.apache.spark.rdd.RDD[(String)]= {
val data = sc.wholeTextFiles("INPUT_PATH")
val files = data.map { case (filename, content) => filename}
(files)
}
}
When I compile this code using sbt it gives me the error :
value wholeTextFiles is not a member of org.apache.spark.SparkContext.
I am importing all of which is required but it's still giving me this errror.
But when I compile this code by replacing wholeTextFiles with textFile, the code gets compiled.
What might be the problem here and how do I resolve that?
Thanks in advance!
Environment:
Scala compiler version 2.10.2
spark-1.2.0
Error:
[info] Set current project to RecipeIO (in build file:/home/akshat/RecipeIO/)
[info] Compiling 1 Scala source to /home/akshat/RecipeIO/target/scala-2.10.4/classes...
[error] /home/akshat/RecipeIO/src/main/scala/RecipeIO.scala:14: value wholeTexFiles is not a member of org.apache.spark.SparkContext
[error] val data = sc.wholeTexFiles(INPUT_PATH)
[error] ^
[error] one error found
[error] {file:/home/akshat/RecipeIO/}default-55aff3/compile:compile: Compilation failed
[error] Total time: 16 s, completed Jun 15, 2015 11:07:04 PM
My build.sbt file looks like this :
name := "RecipeIO"
version := "1.0"
scalaVersion := "2.10.4"
libraryDependencies += "org.apache.spark" % "spark-core_2.10" % "0.9.0-incubating"
libraryDependencies += "org.eclipse.jetty" % "jetty-server" % "8.1.2.v20120308"
ivyXML :=
<dependency org="org.eclipse.jetty.orbit" name="javax.servlet" rev="3.0.0.v201112011016">
<artifact name="javax.servlet" type="orbit" ext="jar"/>
</dependency>
You have a typo: it should be wholeTextFiles instead of wholeTexFiles.
As a side note, I think you want sc.wholeTextFiles(INPUT_PATH) and not sc.wholeTextFiles("INPUT_PATH") if you really want to use the INPUT_PATH variable.

Reproducing a ScalaCheck test run

This was asked as a "bonus question" in https://stackoverflow.com/questions/12639454/make-scalacheck-tests-deterministic, but not answered:
Is there a way to print out the random seed used by ScalaCheck, so that you can reproduce a specific test run?
There is a hacky way: wrap a random generator to print its seed on initialization and pass it to Test.Parameters. Is there a better option?
As of today, this is possible (see scalacheck#263).
There are some nice examples here: Simple example of using seeds with ScalaCheck for deterministic property-based testing.
In short, you can do:
propertyWithSeed("your property", Some("seed")) =
forAll { ??? }
and the seed will be printed when this property fails.
There is no way to do this today. However, it will be implemented in the future, see https://github.com/rickynils/scalacheck/issues/67
This is my answer there:
Bonus question: Is there an official way to print out the random seed used by ScalaCheck, so that you can reproduce even a non-deterministic test run?
From specs2-scalacheck version 4.6.0 this is now a default behaviour:
Given the test file HelloSpec:
package example
import org.specs2.mutable.Specification
import org.specs2.ScalaCheck
class HelloSpec extends Specification with ScalaCheck {
package example
import org.specs2.mutable.Specification
import org.specs2.ScalaCheck
class HelloSpec extends Specification with ScalaCheck {
s2"""
a simple property $ex1
"""
def ex1 = prop((s: String) => s.reverse.reverse must_== "")
}
build.sbt config:
ThisBuild / scalaVersion := "2.13.0"
ThisBuild / version := "0.1.0-SNAPSHOT"
ThisBuild / organization := "com.example"
ThisBuild / organizationName := "example"
lazy val root = (project in file("."))
.settings(
name := "specs2-scalacheck",
libraryDependencies ++= Seq(
"org.specs2" %% "specs2-core" % "4.6.0",
"org.specs2" %% "specs2-matcher-extra" % "4.6.0",
"org.specs2" %% "specs2-scalacheck" % "4.6.0"
).map(_ % "test")
)
When you run the test from the sbt console:
sbt:specs2-scalacheck> testOnly example.HelloSpec
You get the following output:
[info] HelloSpec
[error] x a simple property
[error] Falsified after 2 passed tests.
[error] > ARG_0: "\u0000"
[error] > ARG_0_ORIGINAL: "猹"
[error] The seed is X5CS2sVlnffezQs-bN84NFokhAfmWS4kAg8_gJ6VFIP=
[error]
[error] > '' != '' (HelloSpec.scala:11)
[info] Total for specification HelloSpec
To reproduce that specific run (i.e with the same seed), you can take the seed from the output and pass it using the command line scalacheck.seed:
sbt:specs2-scalacheck>testOnly example.HelloSpec -- scalacheck.seed X5CS2sVlnffezQs-bN84NFokhAfmWS4kAg8_gJ6VFIP=
And this produces the same output as before.
You can also set the seed programmatically using setSeed:
def ex1 = prop((s: String) => s.reverse.reverse must_== "").setSeed("X5CS2sVlnffezQs-bN84NFokhAfmWS4kAg8_gJ6VFIP=")
Yet another way to provide the Seed is pass an implicit Parameters where the seed is set:
package example
import org.specs2.mutable.Specification
import org.specs2.ScalaCheck
import org.scalacheck.rng.Seed
import org.specs2.scalacheck.Parameters
class HelloSpec extends Specification with ScalaCheck {
s2"""
a simple property $ex1
"""
implicit val params = Parameters(minTestsOk = 1000, seed = Seed.fromBase64("X5CS2sVlnffezQs-bN84NFokhAfmWS4kAg8_gJ6VFIP=").toOption)
def ex1 = prop((s: String) => s.reverse.reverse must_== "")
}
Here is the documentation about all those various ways.
This blog also talks about this.

Writing a custom matcher for NodeSeq

I'm trying to write a simple custom matcher for NodeSeq, with scalatest v.2.0.M5b.
package test
import org.scalatest.matchers.{MatchResult, Matcher, ShouldMatchers}
import scala.xml.NodeSeq
import org.scalatest.FunSpec
class MySpec extends FunSpec with ShouldMatchers with MyMatcher {
describe("where is wrong?") {
it("showOK") {
val xml = <span>abc</span>
xml should contn("b")
}
}
}
trait MyMatcher {
class XmlMatcher(str: String) extends Matcher[NodeSeq] {
def apply(xml: NodeSeq) = {
val x = xml.toString.contains(str)
MatchResult(
x,
"aaa",
"bbb"
)
}
}
def contn(str: String) = new XmlMatcher(str)
}
When I compile it, it reports error:
[error] /Users/freewind/src/test/scala/test/MyMacher.scala:14: overloaded method value should with alternatives:
[error] (beWord: MySpec.this.BeWord)MySpec.this.ResultOfBeWordForAnyRef[scala.collection.GenSeq[scala.xml.Node]] <and>
[error] (notWord: MySpec.this.NotWord)MySpec.this.ResultOfNotWordForAnyRef[scala.collection.GenSeq[scala.xml.Node]] <and>
[error] (haveWord: MySpec.this.HaveWord)MySpec.this.ResultOfHaveWordForSeq[scala.xml.Node] <and>
[error] (rightMatcher: org.scalatest.matchers.Matcher[scala.collection.GenSeq[scala.xml.Node]])Unit
[error] cannot be applied to (MySpec.this.XmlMatcher)
[error] xml should contn("b")
[error] ^
[error] one error found
[error] (test:compile) Compilation failed
Where is wrong?
Update:
The build.sbt file I use:
name := "scalatest-test"
scalaVersion := "2.10.1"
version := "1.0"
resolvers ++= Seq("snapshots" at "http://oss.sonatype.org/content/repositories/snapshots",
"releases" at "http://oss.sonatype.org/content/repositories/releases",
"googlecode" at "http://sass-java.googlecode.com/svn/repo"
)
libraryDependencies += "org.scalatest" %% "scalatest" % "2.0.M5b" % "test"
And a demo project: https://github.com/freewind/scalatest-test
For the reason why scala compiler complains see this answer.
But it seems that ScalaTest API has changed quite a bit since then, so the two solutions proposed both need some modification (tested for ScalaTest 2.0.M5b):
Replace All instances of NodeSeq to GenSeq[Node] so that the type matches everywhere.
See SeqShouldWrapper class of ScalaTest.
Alternatively, wrap xml explicitely with the conversion function, i.e. manually setting the required type but I don't recommend this because it makes client code ugly.
new AnyRefShouldWrapper(xml).should(contn("b"))
BTW, it is good to have a small but complete project on github for others to tweak. It makes this question much more attractive.