Archive

Archive for May, 2011

Comparison of IDEs for Scala development

May 16th, 2011 1 comment

Although all my coding is done using Vim for editing and console tools for compiling, IDEs are the best alternative for other tasks like debugging or refactoring code. Since I’m exploring the Scala ecosystem I’ve done some research about which IDE best suits my coding requirements. Those are:

  • Unobtrusive SBT integration. As I said, I will use the IDE for debugging from time to time, and thus it should not interfere with the command line + Vim ecosystem.
  • The IDE must mix Java and Scala code in the project without any problem
  • Enable debugging of Scala applications
  • Provide refactoring of Scala code

The IDEs under test will be Eclipse, Netbeans and IntelliJ

Eclipse Helios (3.6.2)

After downloading Eclipse, the first thing to do is to install the Scala plugin and the SBT plugin. The Scala plugin is installed into the IDE itself but the SBT plugin has to be added into the SBT plugins section in project/plugins/YourProjectPlugins.scala. Putting IDE information in my project’s build instructions is something I don’t like at all. The plugin needs that you add the trait Eclipsify to your project definition, so this goes against the “Unobtrusive SBT integration”. In summary, the installation needs that you put

 lazy val sbtEclipsify = "de.element34" % "sbt-eclipsify" % "0.4.0"

in your project/plugins/YourProjectPlugins.scala file and to add the import and mix the trait in your project/build/TestProject.scala file

 import sbt._
import de.element34.sbteclipsify._

class TestProject(info: ProjectInfo) extends DefaultProject(info)
                                     with Eclipsify
{
...
}

In order to create the Eclipse project files, just fire sbt, and perform

sbt
> update
> eclipse

Now we can open the project and it looks like:

Thinks that I miss:

  • No console integration with SBT
  • Test are not recognized as such and thus, if you are debugging your unit tests you are out of luck.
  • Refactoring capabilities are very much limited (I was not able to find the simplest one, rename a class)

Netbeans (7.0)

The first thing is to install the Scala support for Netbeans grabbing the plugin from here. The SBT plugin for Netbeans includes a processor that allows you to create project skeletons within the sbt console. But the general functioning of the plugin is similar to the Eclipse one, you have to modify your project definition for running it. Follow instructions in Running the plugin.

The project looks like this in Netbeans.

Issues with Netbeans:

  • Netbeans uses internally SBT for all the compilation tasks, so this is a plus.
  • Although you can run SBT commands with the console, they are detached from the whole IDE. For instance, you can run the test phase but the IDE won’t stop in the breakpoints.
  • And the other way round does not work either. If you Right-click in a test, Netbeans complains that some classes can not be found.
  • Refactoring is full supported and it can perform usual code modifications. Great!!

IntelliJIDEA (10.0.3 Community Edition)

Again, first install the IDEA Scala plugin (can be downloaded going to File->Settings->Plugins). The SBT plugin that generates an IDEA project from our SBT project is better than the previous ones. Although it can be used as a normal SBT plugin in case all our team were using the IntelliJ IDE, its main advantage is that it can be used as a SBT processor. SBT processors are complementary to SBT plugins, but they are invoked on a per user basis instead of a per project like plugins do. They are thus unobtrusive and leaves no IDE traces in our project definition. Just write


sbt

> *sbtIdeaRepo at http://mpeltonen.github.com/maven/
> *idea is com.github.mpeltonen sbt-idea-processor 0.4.0

> update

> idea

Now we have our project files in the directory. Screenshots of the IntelliJ code editing panels and debugging capabilities.

So in general IntelliJ has all what I was looking for

  • Unobtrusive SBT support by means of an SBT processor
  • Coding and refactoring capabilities for the Scala and Java language
  • Debugging of full Scala projects or just one unit test
  • Full SBT console integration in the IDE.

Conclusion

So, the winner is clearly the IntelliJ IDE and a second place for Netbeans. I’ve never liked Eclipse and this time it was no exception.

Just one caveat. As I said I will use the IDE just a 10 percent of my time and thus this research has not been exhaustive. I fired up the three IDEs, followed basic instructions for Scala and SBT support and when things did not work as expected I’ve done a minimal work trying to fix it. It does not pay for me. So, If you think that I was wrong in one of the IDEs or that just a little tweak could recover one of the evaluations, I will be glad hearing your comments.

Categories: Programming Tags: , , , , ,

Simple Scala project step-by-step

May 2nd, 2011 6 comments

BE AWARE!!! This post refers to an old SBT version, check the new one

 

Recently I have started a project that will be coded in Scala. Here I leave some instructions for setting up the the scala project that uses sbt for project management and creates unit tests with scalatests. This entry follows the structure of this post but introduces some changes and improvements.

  1. Install sbt
  2. Create a new project
    $ mkdir test-project
    $ cd test-project/
    $ sbt
    Project does not exist, create new project? (y/N/s) y
    Name: TestProject
    Organization: com.example
    Version [1.0]:
    Scala version [2.7.7]: 2.9.0
    sbt version [0.7.4]: 0.7.7
    
  3. First we need to install a sbt plugin that collects test results and creates a xUnit report for using in a Continuous Integration Server like Jenkins. Details of that plugin can be found here. Create the file project/plugins/TestProjectPlugins.scala that instructs sbt to download the junit_xml_listener plugin.
    import sbt._
    
    class TestProjectPlugins(info: ProjectInfo) extends PluginDefinition(info) {
        val repo = "Christoph's Maven Repo" at "http://maven.henkelmann.eu/"
        val junitXml = "eu.henkelmann" % "junit_xml_listener" % "0.2"
    }
    
  4. Once we have the configuration for getting the plugin, create the project dependencies and include the new listener into the available ones by overriding the defaults. So, create a build configuration file in project/build/TestProject.scala like:
    import sbt._
    import eu.henkelmann.sbt.JUnitXmlTestsListener
    
    class TestProject(info: ProjectInfo) extends DefaultProject(info) {
       val scalatest = "org.scalatest" %% "scalatest" % "1.6.1" % "test"
    
       //create a listener that writes to the normal output directory
       def junitXmlListener: TestReportListener = new JUnitXmlTestsListener(outputPath.toString)
       //add the new listener to the already configured ones
       override def testListeners: Seq[TestReportListener] = super.testListeners ++ Seq(junitXmlListener)
    }
    
  5. Now, we have the project setup in place. Let’s write some classes and tests in order to check that everything is OK. First create the class under test in src/main/scala/Calc.scala
    package com.example
    
    object Calc {
        def add(x:Int, y:Int) : Int = x + y
    }
    
  6. Now, create a test in src/test/scala/CaltTest.scala that assures that the class is working as expected
    package com.example.test
    
    import com.example.Calc
    import org.scalatest.Suite
    
    class CalcTest extends Suite {
    
        def testAddition() {
            assert(4 === Calc.add(2,2))
        }
    }
    
  7. Now just test that tests pass by doing
    sbt clean-plugins
    sbt clean
    sbt update
    sbt test
    

    you should see something like this:

    $ sbt test
    [info] Building project test 1.0 against Scala 2.9.0
    [info]    using TestProject with sbt 0.7.7 and Scala 2.7.7
    [info]
    [info] == compile ==
    [info]   Source analysis: 0 new/modified, 0 indirectly invalidated, 0 removed.
    [info] Compiling main sources...
    [info] Nothing to compile.
    [info]   Post-analysis: 3 classes.
    [info] == compile ==
    [info]
    [info] == test-compile ==
    [info]   Source analysis: 0 new/modified, 0 indirectly invalidated, 0 removed.
    [info] Compiling test sources...
    [info] Nothing to compile.
    [info]   Post-analysis: 1 classes.
    [info] == test-compile ==
    [info]
    [info] == copy-test-resources ==
    [info] == copy-test-resources ==
    [info]
    [info] == copy-resources ==
    [info] == copy-resources ==
    [info]
    [info] == test-start ==
    [info] == test-start ==
    [info]
    [info] == com.example.test.CalcTest ==
    [info] CalcTest:
    [info] - testAddition
    [info] - testAdditionWithJavaObject
    [info] == com.example.test.CalcTest ==
    [info]
    [info] == test-complete ==
    [info] == test-complete ==
    [info]
    [info] == Test cleanup 1 ==
    [info] Deleting directory /tmp/sbt_b7e36ab4
    [info] == Test cleanup 1 ==
    [info]
    [info] == test-finish ==
    [info] Passed: : Total 2, Failed 0, Errors 0, Passed 2, Skipped 0
    [info]
    [info] All tests PASSED.
    [info] == test-finish ==
    [info]
    [info] == test-cleanup ==
    [info] == test-cleanup ==
    [info]
    [info] == test ==
    [info] == test ==
    [success] Successful.
    [info]
    [info] Total time: 1 s, completed 24-ago-2011 15:40:26
    [info]
    [info] Total session time: 2 s, completed 24-ago-2011 15:40:26
    [success] Build completed successfully.
    

The test reports are located in target/scala_*/test-reports/*.xml. I have setup a Mercurial project with all this code for fast start up, check it out here.

Categories: Programming Tags: , , ,