Run tests in all project modules from submodule

1,054 views
Skip to first unread message

Richard Wallace

unread,
Jul 31, 2013, 5:57:23 PM7/31/13
to simple-b...@googlegroups.com
Hello all,

I've got a project setup like the following

  myapp/
    project/
      Build.scala
    module1/
    module2/
    ...
    app/

Each of `module1`, `module2`, etc and `app` have source and tests.  `app` depends on each of the other sub modules.  

I'm writing a deployment task for the `app` module so that we can just run `sbt ";project app; deploy-app"`.  This is similar in nature to the sbt-release plugin (which we use for other purposes).  During the deployment process I want to run all the tests for all the modules.  But I can't figure out how to get that done.  Since the active project is the `app` module, only the tests for that module are built and run.  I had hoped that using `dependsOn(bar % "test->test;compile->compile")` would cause the the modules tests to be run, but it only causes them to be compiled.  Is there any way to accomplish what I'm trying to do?

Thanks,
Rich

Josh Suereth

unread,
Aug 1, 2013, 1:08:49 PM8/1/13
to simple-b...@googlegroups.com
You either want to use aggregates, or make your own test task which directly aggregates the one you want.

e.g., if oyu don't want "myapp" to run all sub-tests, you can make a new dummy project called all:

object MyBuild extends Build {

  val myapp = Project(.....
  // Other projects similarly configured

  val all = Project("all", file("dontuseme")) aggregate(myapp, module1, module2)
}



Now, inside sbt you can just type `all/test`  and it will run all your tests.


--
You received this message because you are subscribed to the Google Groups "simple-build-tool" group.
To unsubscribe from this group and stop receiving emails from it, send an email to simple-build-t...@googlegroups.com.
To post to this group, send email to simple-b...@googlegroups.com.
Visit this group at http://groups.google.com/group/simple-build-tool.
For more options, visit https://groups.google.com/groups/opt_out.
 
 

Richard Wallace

unread,
Aug 1, 2013, 1:38:16 PM8/1/13
to simple-build-tool
That's fine for running tests from the sbt console.  But I want to be able to run all the tests from a task and also create an assembly using the sbt-assembly plugin. The flow is something more like

  * build assembly
  * upload to deployment server
  * run tests
  * report test results to deployment server

This is currently done with shell scripts and I'm trying to move it into an sbt task because the shell scripts have proven error prone.

The idea of using a dummy project module which aggregates the others is interesting, but is there a way to build an assembly in that project?  IIUC, the sbt-assembly plugin only works with dependencies, so that wouldn't work.

I do already have a project that aggregates all the other modules, called `myapp`.  If I could have the task defined for the `app` project run the tests from that project, that would work, but I have no idea how to do that.

Thanks,
Rich

Mark Harrah

unread,
Aug 1, 2013, 5:29:04 PM8/1/13
to simple-b...@googlegroups.com
Hi Rich,

On Wed, 31 Jul 2013 14:57:23 -0700 (PDT)
Richard Wallace <rwal...@thewallacepack.net> wrote:

> Hello all,
>
> I've got a project setup like the following
>
> myapp/
> project/
> Build.scala
> module1/
> module2/
> ...
> app/
>
> Each of `module1`, `module2`, etc and `app` have source and tests. `app`
> depends on each of the other sub modules.
>
> I'm writing a deployment task for the `app` module so that we can just run
> `sbt ";project app; deploy-app"`.

(Side note: app/deploy-app will usually do the same thing.)

> This is similar in nature to the
> sbt-release plugin (which we use for other purposes). During the
> deployment process I want to run all the tests for all the modules. But I
> can't figure out how to get that done. Since the active project is the
> `app` module, only the tests for that module are built and run. I had
> hoped that using `dependsOn(bar % "test->test;compile->compile")` would
> cause the the modules tests to be run, but it only causes them to be
> compiled.

In case it isn't clear, test->test concerns configurations, not tasks. The 'compile' and 'test' configurations group the produced artifacts and using the 'test' configuration would only cause tests to be run if you explicitly require tests to be run before dependents can use the produced artifacts. (Not sure if that made sense.)

> Is there any way to accomplish what I'm trying to do?

0.13 has an API for getting values for multiple projects or in general, multiple scopes:

http://www.scala-sbt.org/0.13.0/docs/Detailed-Topics/Tasks.html#getting-values-from-multiple-scopes

That doesn't help if you aren't on 0.13 of course, but if that is what you want, we can approximate it in 0.12.

-Mark

Mark Harrah

unread,
Aug 1, 2013, 5:29:50 PM8/1/13
to simple-b...@googlegroups.com
On Thu, 1 Aug 2013 13:08:49 -0400
Josh Suereth <joshua....@gmail.com> wrote:

> You either want to use aggregates, or make your own test task which
> directly aggregates the one you want.
>
> e.g., if oyu don't want "myapp" to run all sub-tests, you can make a new
> dummy project called all:
>
> object MyBuild extends Build {
>
> val myapp = Project(.....
> // Other projects similarly configured
>
> val all = Project("all", file("dontuseme")) aggregate(myapp, module1,
> module2)
> }
>
>
>
> Now, inside sbt you can just type `all/test` and it will run all your
> tests.

In his case, he wanted to do it programmatically. Aggregation is only a command-line convenience.

-Mark

Richard Wallace

unread,
Aug 1, 2013, 5:47:59 PM8/1/13
to simple-build-tool
That does look helpful.  IIUC, I could have my deployment task live in the root project and get the jar assembled by sbt-assembly in the `app` sub-project.  Running tests would run all the tests because my root project aggregates all the modules.  
 
That doesn't help if you aren't on 0.13 of course, but if that is what you want, we can approximate it in 0.12.

I've tried updating our project to 0.13-RC4, but one of the plugins we use doesn't have a build for it yet.  What would be the 0.12 approximate?

Thanks,
Rich

Mark Harrah

unread,
Aug 2, 2013, 9:52:23 AM8/2/13
to simple-b...@googlegroups.com
You would define a custom task that depends on the test tasks you want to run. For example, you might redefine the root project test task as:

val select = ScopeFilter(
inAggregates(root, includeRoot = false),
inConfigurations(Test)
)

test in Test := test.all(select).value

> > That doesn't help if you aren't on 0.13 of course, but if that is what you
> > want, we can approximate it in 0.12.
> >
>
> I've tried updating our project to 0.13-RC4, but one of the plugins we use
> doesn't have a build for it yet. What would be the 0.12 approximate?

test in Test <<= Defaults.forDependencies(proj => test in proj in Test, includeRoot = false, classpath = true, aggregate = false) { tasks =>
tasks.join.map(_ => ())
}

This defines a test task that depends on the test tasks in all transitive dependencies of the current project. classpath=true means the dependencies are the standard x.dependsOn(y) dependencies. Set aggregate=true to also include x.aggregate(y) dependencies.

The first proj => ... defines what key is selected given a project proj. forDependencies returns the tasks but doesn't evaluate them, so this is what the tasks.join is for. map(_ => ()) discards the Seq[Unit] obtained as a result of evaluating the multiple test tasks.

-Mark

Richard Wallace

unread,
Aug 2, 2013, 1:26:24 PM8/2/13
to simple-build-tool
On Thu, Aug 1, 2013 at 2:29 PM, Mark Harrah <dmha...@gmail.com> wrote:
Hi Rich,

On Wed, 31 Jul 2013 14:57:23 -0700 (PDT)
Richard Wallace <rwal...@thewallacepack.net> wrote:

> Hello all,
>
> I've got a project setup like the following
>
>   myapp/
>     project/
>       Build.scala
>     module1/
>     module2/
>     ...
>     app/
>
> Each of `module1`, `module2`, etc and `app` have source and tests.  `app`
> depends on each of the other sub modules.
>
> I'm writing a deployment task for the `app` module so that we can just run
> `sbt ";project app; deploy-app"`.

(Side note: app/deploy-app will usually do the same thing.)

That works for tasks, but not commands, is that right?

Mark Harrah

unread,
Aug 2, 2013, 1:31:27 PM8/2/13
to simple-b...@googlegroups.com
On Fri, 2 Aug 2013 10:26:24 -0700
Richard Wallace <rwal...@thewallacepack.net> wrote:

> On Thu, Aug 1, 2013 at 2:29 PM, Mark Harrah <dmha...@gmail.com> wrote:
>
> > Hi Rich,
> >
> > On Wed, 31 Jul 2013 14:57:23 -0700 (PDT)
> > Richard Wallace <rwal...@thewallacepack.net> wrote:
> >
> > > Hello all,
> > >
> > > I've got a project setup like the following
> > >
> > > myapp/
> > > project/
> > > Build.scala
> > > module1/
> > > module2/
> > > ...
> > > app/
> > >
> > > Each of `module1`, `module2`, etc and `app` have source and tests. `app`
> > > depends on each of the other sub modules.
> > >
> > > I'm writing a deployment task for the `app` module so that we can just
> > run
> > > `sbt ";project app; deploy-app"`.
> >
> > (Side note: app/deploy-app will usually do the same thing.)
> >
>
> That works for tasks, but not commands, is that right?

Right.

-Mark

Richard Wallace

unread,
Aug 2, 2013, 2:41:34 PM8/2/13
to simple-build-tool
This worked perfectly, thanks!

Rich
Reply all
Reply to author
Forward
0 new messages