importing files to test functions in clojure - unit-testing

i have a main src folder which has another folder say xyz which has a main.clj file , i have another folder test which has folder xyz and file main_test.clj , but when i run : lein test it says :
lein test user
Ran 0 tests containing 0 assertions.
0 failures, 0 errors.
i need to test functions of main.clj , i am very new to clojure any help would be great.
--- project1
|____src
| |_____main.clj
|_____test
| |_____main_test.clj
|_____project.clj
i have tried different ways with require and load . i have to write the unit tests .

If your source file is src/xyz/main.clj and its ns form calls it xyz.main, then make sure you have test/xyz/main_test.clj and its ns form calls it xyz.main-test -- note the hyphen there corresponding to the _ in the filename.
If that intermediate folder is x_y_z then the corresponding namespace segment would be x-y-z.

You need to add the test directory to the classpath for running tests. This is for Leiningen done in project.clj:
(defproject project1
…
:test-paths ["test"]
…)

Sean has some good points. If that doesn't work, try the following to get a baseline setup that runs:
~/expr > lein new app sample
~/expr > cd sample
~/expr/sample > lein test
lein test sample.core-test
lein test :only sample.core-test/a-test
FAIL in (a-test) (core_test.clj:7)
FIXME, I fail.
expected: (= 0 1)
actual: (not (= 0 1))
Ran 1 tests containing 1 assertions.
1 failures, 0 errors.
Tests failed.

Related

How to run the command lein run automatically after save?

In a Leiningen project, I want to be able to run lein run each time I save a file in my project. How can I do that?
The best way is using the
lein test-refresh plugin.
This will monitor the file system, and re-run your unit tests upon each file save. Simply make a unit test that calls (myproj.core/-main) or similar, and on each file save your program will re-run.
An even better way is to write a unit test that runs one or more functions (possibly including -main), and compares the actual output to the expected output.
Don't forget to look at the :test-refresh/focus metadata, which will allow you to select specific tests to run, temporarily ignoring others.
I use both features extensively in my lib Tupelo Clojure, which has over 3500 unit tests. As an example, please see the Clojure Template project:
~/demo > git clone git#github.com:io-tupelo/clj-template.git
Cloning into 'clj-template'...
~/demo >
~/demo > cd clj-template
~/demo/clj-template > lein test
lein test _bootstrap
-------------------------------
Clojure 1.10.1 Java 13
-------------------------------
lein test tst.demo.core
Ran 3 tests containing 8 assertions.
0 failures, 0 errors.
~/demo/clj-template >
and the code:
(ns tst.demo.core
(:use demo.core tupelo.core tupelo.test)
(:require
[tupelo.string :as ts])
(:import [demo Calc]))
(dotest
(is= 5 (+ 2 3))
(isnt= 9 (+ 2 3))
(throws? (/ 1 0)) ; verify that an illegal operation throws an exception
(is= 3 (add2 1 2))
(throws? (add2 1 "two"))) ; Prismatic Schema will throw since "two" is not a number
If you use tupelo.test like the above, you can just substitute (dotest-focus ...) instead of dotest and only that particular test(s) will run.
Another example is the JUXT/bidi demo.
Enjoy!
Update
If you want to investigate an alternate Leiningen test runner, please see the Koacha lib.

Gradle test task - Gradle 1.6 and with Gradle 2.3 or later

I have a Java project.
PS: In my project, I don't have any java program/source code in src/test/java. - This folder just contains a blank.txt file.
I have two different Gradle versions:
Gradle 1.6 with Java 7 (as Java 8 is NOT compatible with Gradle 1.6 or any version < less than 1.10 version if I'm correct).
The other version is: Gradle 2.3 with Java 8.
Using both of the above mentioned Gradle 1.6 + Java7 OR Gradle 2.3 + Java 8 versions my project build successfully.
Though, I noticed one thing: That while running the build, it calls "test" task automatically (as per the Gradle design, test task runs for free); I found during Gradle 1.6 + Java7 run --- I see the following output.
:jar
:assemble
:compileTestJava UP-TO-DATE
:processTestResources
:testClasses
:test
:check
As you'll notice, it says I don't have any test source code (i.e. src/test/java doesn't contain any source code OR there's nothing new for Gradle to compile this time may be nothing changed since last time gradle ran the build) and that's why compileTestJava task is showing UP-TO-DATE in front of it.
But, :test task is showing that it ran successfully. I have used jacoco (code coverage) section within test { .. } task, then it actually ran that part (as there is no UP-TO-DATE in front of test task). Jacoco section is NOT defined in my project's build.gradle but actually it's coming from a top level / GRADLE_HOME/init.d/some-common-top-level.gradle file (where test { ... has jacoco { ... } .. } section in it).
As I mentioned above, test task didn't say UP-TO-DATE, therefore, after Gradle build process was complete, I can see it created the following folder/files structure inside build/tmp/expandedArchives/org.jacoco.... folder:
$ ls -ltr build/tmp/expandedArchives/
total 4
drwxr-xr-x+ 1 e020001 Domain Users 0 Jul 7 20:45 org.jacoco.agent-0.7.2.201409121644.jar_778m6tp3jrtvcetasufl59dmau
$ ls -ltr build/tmp/expandedArchives/org.jacoco.agent-0.7.2.201409121644.jar_778m6tp3jrtvcetasufl59dmau/
total 272
drwxr-xr-x+ 1 e020001 Domain Users 0 Jul 7 20:58 META-INF
-rwxr-xr-x 1 e020001 Domain Users 2652 Jul 7 20:58 about.html
-rwxr-xr-x 1 e020001 Domain Users 272311 Jul 7 20:58 jacocoagent.jar
drwxr-xr-x+ 1 e020001 Domain Users 0 Jul 7 20:58 org
The same is NOT happening when I'm running Gradle 2.3 and Java8.
Build is successful but I'm not getting build/tmp/expandedArchives/org.jacoco.... folder containing jacocoagent.jar file.
Any idea, why Gradle 2.3 is not creating this jacoco specific .jar file.
With Gradle 2.3+Java8, the following output shows UP-TO-DATE in front of both :compileTestJava and :test tasks (which was not the case with Gradle 1.6 for test task).
I ran "gradle clean build".
:compileTestJava UP-TO-DATE
:compileTestGroovy UP-TO-DATE
:processTestResources
:testClasses
:test UP-TO-DATE
:check
I need Gradle 2.3 to generate this jacocoagent.jar under build/tmp/expandedArchives/org.jacoco..... folder so that I can use it in a downstream Jenkins job (which runs non-Unit tests) as this project does have some Integration tests and I'm fetching the jacocoagent.jar from the parent main build job (which runs gradle clean build including test task) in downstream job so that I can pass it to TOMCAT JVM while starting Tomcat (so that I can get jacocoIT.exec code coverage for IT tests). But, after I switched to Gradle 2.3, all projects where I don't have src/test/java ... now jacocoagent.jar is not getting created and the copy artifact plugin fails while trying to copy the .jar file from parent job.
One more point:
With Gradle 1.6 + Java7, if I run gradle clean build, it successfully creates that jacocoagent.jar inside build/tmp/expandedArchives/org.jacoco..... folder but it works this way, only when I run gradle clean build or "gradle clean; gradle test".
If I run gradle clean build, and then remove build/tmp folder, and now just run: gradle test, it shows me UP-TO-DATE in front of both :compileTestJava and :test tasks and doesn't create build/tmp/expandedArchives/org.jacoco.... folder containing jacocoagent.jar file.
For more info, I'm attaching the profile run (i.e. using --profile option) while running gradle test task for Gradle 1.6 + java 7.
I see that, in the profile html file that when test task is run, it first calls compileJava as per Gradle process logic and then test task and it's also calling depedencies --- :jacocoAgent (as per the dependency resolution tab):
But,
with Gradle 2.3 + Java8, the dependency Resolution / order and Task execution step is not same (or in the order as compared to Gradle 1.6) for generating or showing any reference to jacocoAgent dependency as it's not even calling it.
Running Gradle1.6 +Java7 test task with -i (or --info) option shows why it ran test task even though I had no test source code, see the reason why:
Note: Recompile with -Xlint:unchecked for details.
:processResources
Skipping task ':processResources' as it has no source files.
:processResources UP-TO-DATE
:classes
Skipping task ':classes' as it has no actions.
:compileTestJava
Skipping task ':compileTestJava' as it has no source files.
:compileTestJava UP-TO-DATE
:processTestResources
Executing task ':processTestResources' due to:
No history is available.
:testClasses
Skipping task ':testClasses' as it has no actions.
:test
file or directory '/my/workspace/project/build/classes/test', not found
Executing task ':test' due to:
No history is available.
file or directory '/my/workspace/project/build/classes/test', not found
Finished generating test XML results (0.001 secs)
Generating HTML test report...
Finished generating test html results (0.012 secs)
BUILD SUCCESSFUL
you can force the test task to be executed no matter what the status of inputs and outputs are:
test{
outputs.upToDateWhen{false}
}
for earlier gradle versions you can ensure the class directory exists by
task createTestClassesDir << {sourceSets.test.output.classesDir.mkdirs()}
test.dependsOn createTestClassesDir
Summary:
With Gradle 2.3, if there are no valid .java/.groovy (or etc) test code, then test task won't even run and thus there'll be no jacocoagent.jar created somewhere deep in build/tmp/exapandedArchives/org.jacoco.xxx.... folder.
Solution was to include the following (in top level $GRADLE_HOME/init.d/some-global-file.gradle) inside allprojects { .... } section. All we are doing is, if src/test/java (standard) or any legacy folder structure (src/java if your project structure is like this) doesn't have any valid test source code, then we can add a dummy test file (DummyTestXYZ.java or groovy) and let test task run which will generate jacocoagent.jar (which we can use / tie in Tomcat options for generating jacoco report for non-unit aka integration tests). This way, if your main build job calls a downstream/child job to run your IT tests, it won't fail as it can fetch jacocoagent.jar (from main build job's workspace) as test task will create jacocoagent.jar in build/tmp/expandedArchives/org.jacoco.xx.x.xx..x folder (that you can get using Copy Artifact plugin in Jenkins).
PS: Change the if statement logic acc. to your own folder setup i.e. in which folder you'd want to create the DummyTestXYZ.java file. In our case, all new projects were using src/test/java (standard folder structure as per Maven/Gradle standard) and during the new project creation, we are adding valid sample unit tests checked-in to the source control. Thus, in the logic below, we are actually ignoring to create this DummyTestXYZ.java in case src/test/java exists and creating this file only if src/test/java folder doesn't exist in the project (i.e. this is a project which has legacy folder structure) + test/java (legacy folder for storing JUnit unit tests) has no .java programs and/or if test/java doesn't exist then create it first and then create the dummy file. I know, we could have uploaded jacocoagent.jar at some location on Jenkins server and use that file while starting Tomcat for getting code coverage for IT tests. The dummy test file we added requires junit:junit:4.10 or 4.11 library version for the :compileTestJava task to succeed.
compileJava {
doLast {
def dirName = "${projectDir}/test/java"
if(!file( "${projectDir}/src/test/java" ).exists())
if(!file( dirName ).exists())
new File( dirName ).mkdirs()
if(file( dirName ).exists()) {
def javaCnt = new FileNameByRegexFinder().getFileNames(dirName, /.*\.java/).size()
if(javaCnt == 0) {
def f = new File( dirName , 'DummyTestXYZ.java' )
def w = f.newPrintWriter()
w.println('import org.junit.Test;')
w.println('')
w.println('public class DummyTestXYZ {')
w.println('#Test' )
w.println('public void test() {')
w.println('}')
w.println('}')
w.close()
}
}
}
}
test {
doFirst {
testResultsDirName = "test-results/UT"
testReportDirName = "tests/UT"
}
maxParallelForks = 5
forkEvery = 50
//ignoreFailures = true
// Following Jacoco section is required only in Jenkins
// But a developer can uncomment them if they want this feature to work for their
// Desktop local Gradle builds.
jacoco {
//Following vars works only with versions >= 1.7 version of Gradle
destinationFile = file("$buildDir/jacoco/UT/jacocoUT.exec")
}
doLast {
if (file("${projectDir}/test/java/DummyTestXYZ.java").exists()) {
println "++"
println "++"
println "++"
println "======================================================="
println "DEV Team – Please add valid Unit tests in this project."
println "======================================================="
println "++"
println "++"
println "++"
sleep(30 * 1000)
new File("${projectDir}/build/classes/test").deleteDir()
new File("${buildDir}/jacoco/UT").deleteDir()
new File("${buildDir}/test-results/UT").deleteDir()
delete "${projectDir}/test/java/DummyTestXYZ.java"
}
}
}
//Do the same (as above test code) for any other similar test tasks like integartionTest, acceptanceTest etc..
jacocoTestReport {
//cleaning any compile time generated (for ex: JiBx classes files) so that jacoco task won't fail for not finding the actual source files (.java/.groovy for the compile time generated .class files)
doFirst {
delete fileTree (dir: "${buildDir}/classes", include: "**/JiBX_*.class")
}
group = "Reporting"
description = "Generate Jacoco coverage reports after running tests."
//ignoreFailures = true
executionData = fileTree(dir: 'build/jacoco', include: '**/*.exec')
reports {
xml{
enabled true
//Following value is a file
destination "${buildDir}/reports/jacoco/xml/jacoco.xml"
}
csv.enabled false
html{
enabled true
//Following value is a folder
destination "${buildDir}/reports/jacoco/html"
}
}
sourceDirectories = files(['src/java','src/main/java', 'src/main/groovy'])
classDirectories = files('build/classes/main')
doLast {
if (file("${projectDir}/test/java/DummyTestXYZ.java").exists()) {
delete "${projectDir}/test/java/DummyTestXYZ.java"
}
}
}

Lein console (like sbt)

Is there some built-in functionality or plugin to lein to get a lein console, so for example one could test without waiting every time for JVM to start up.
$ lein console
>>> test
...
>>> test
...
>>> jar
Note: I'd like to trigger test runs myself, not e.g. by watching source files. That's why I'd like to have a lein console.
Clarification: I'm not looking for lein repl. I'd like to have a console where I could run lein task commands.
Older versions of leiningen used to include lein interactive, which behaved much like the feature you are asking for: it opened a shell into which you could type test and have it run lein test from the already-running lein jvm, and so on. This feature was removed in the transition to lein 2.0, I think, and although I don't know why I suspect there was a good reason. Maybe try asking in #leiningen on freenode?
You might want to have a look at grenchman. While it's not a Leiningen console it at least enables reusing of an existing REPL session. From what I gather, usage is as follows:
Move somewhere that is not inside a project and call:
$ lein repl :headless
Within your project directory, use:
$ grench lein <task> <options>
Tasks will be run inside the already spun up Leiningen JVM and the startup overhead should disappear.
Building grenchman seems to be tedious, though, and it is recommended to use one of the precompiled binaries (BUT they are currently not available).
And finally, that page also states:
Grenchman is still very new and may not be fully reliable.
So, good luck, I guess?
One option is to run a repl from leiningen's own jar file.
$ java -cp ~/.lein/self-installs/leiningen-2.5.0-standalone.jar clojure.main
Clojure 1.6.0
user=> (require '[leiningen.core.project :as project] '[leiningen.test :as test])
nil
user=> (def prj (project/read))
#'user/prj
user=> (test/test prj)
lein test org.noisesmith.orsos.load-test
Ran 3 tests containing 3 assertions.
0 failures, 0 errors.
nil
user=> (require '[leiningen.jar :as jar])
nil
user=> (jar/jar prj 'org.noisesmith.orsos)
Compiling org.noisesmith.orsos
Created /media/justin/806084F16084EEEA/clojure/orsos/target/orsos-0.1.0-SNAPSHOT.jar
{[:extension "jar"] "/media/justin/806084F16084EEEA/clojure/orsos/target/orsos-0.1.0-SNAPSHOT.jar"}
user=>
As a baseline, this can run lein tasks without having to restart lein every time. If you also use rlwrap or use nrepl it becomes a bit more usable. As far as I know there is no user friendly tooling around this (though there easily could be).
If you wish to use tasks from lein plugins those can be added to the -cp arg.

Leiningen has problems building a working uberjar

We're trying to build our Clojure project with Leiningen. We've succeeded in creating an uberjar by doing the following:
preconditions:
project.clj file lists dependencies
:main my-project.core in project.clj
a core.clj file with a -main function
(:gen-class :main true) in core.clj
procedure:
ran lein test; completed with no failures
ran lein deps; completed successfully
from project.clj's directory: rain lein uberjar
This created two jar files: My-Project-1.0.0-SNAPSHOT-standalone.jar, and My-Project-1.0.0-SNAPSHOT.jar.
ran java -jar BioClojure-1.0.0-SNAPSHOT-standalone.jar, which resulted in this exception:
Exception in thread "main" java.lang.SecurityException: Invalid signature file digest for Manifest main attributes
My research into this problem has not been fruitful. Apparently, it's a known problem with no good solution. I do not understand the answers there.
What do we need to do to get our uberjar working?
determine which of our dependencies is causing the problem?
remove dependencies from our project?
compile the project some other way?
patch leiningen?
use the suggested command: zip *-standalone.jar -d META-INF/DUMMY.SF (I have no idea what this does)
do something with :uberjar-exclusions in the project.clj file? (if so, what?)
Lein and java versions:
$ lein version
Leiningen 1.6.1 on Java 1.6.0_26 Java HotSpot(TM) 64-Bit Server VM
Update: running the command suggested gives:
$ unzip -l BioClojure-1.0.0-SNAPSHOT-standalone.jar | grep -i -e "\.sf"
49911 08-27-09 15:57 META-INF/RCSB-PDB.SF
0 03-23-10 08:21 META-INF/maven/net.sf.alxa/
0 03-23-10 08:21 META-INF/maven/net.sf.alxa/jlatexmath/
929 03-23-10 08:20 META-INF/maven/net.sf.alxa/jlatexmath/pom.xml
115 03-21-10 14:01 META-INF/maven/net.sf.alxa/jlatexmath/pom.properties
175241 08-17-11 20:25 META-INF/SELFSIGN.SF
0 09-21-09 06:45 META-INF/maven/net.sf.opencsv/
0 09-21-09 06:45 META-INF/maven/net.sf.opencsv/opencsv/
5510 09-21-09 06:44 META-INF/maven/net.sf.opencsv/opencsv/pom.xml
106 09-21-09 06:45 META-INF/maven/net.sf.opencsv/opencsv/pom.properties
My understanding from reading the comments in that issue is that your problem would go away if you add the following to your project.clj
:uberjar-exclusions [#"foo.sf"]
where foo.sf is the particular .sf file you want to ignore from the jar. You can determine this by running:
unzip -l BioClojure-1.0.0-SNAPSHOT-standalone.jar | grep -i -e "\.sf"
The suggested zip command deletes the particular file from the jar (which is of the ZIP format).

How do I add unit tests to a Leiningen project?

I noticed that leiningen has a great unit test plugin - you just enter "lein test" :) . However, it's not clear how it "finds" the test files. Is there a specific folder I need to put them in? Or, if its just scanning namespaces (which is what it says in the lein docs), how do I know what namespace I need to use for leiningen to see my tests?
I was thinking about simply making one test file, called tests.clj. A sample template would really be nice.
At the top level make a test/ directory, and then create some file, say mytests.clj. Here's a sample (caveat: I didn't actually compile this, but simplified an existing test):
(ns mytests
(:use clojure.test))
(defn myfixture [block]
(do
(println "before test")
(block)
(println "after test")))
(use-fixtures :each myfixture)
(deftest mytest
(is (= 2 (+ 1 1))))
for lein version 2.7.1 : {this is from Linux Mint with Leiningen 2.7.1 on Java 1.8.0_121 Java HotSpot(TM) 64-Bit Server VM }
I wanted to do more with testing and now have this new knowledge...
lein new <projname>
cd <projname>
tree -d
cat test/<projname>/core_test.clj
lein test
-> observe failing test template even on blank new project
then you could add: (print "start adding test")
and see your efforts ...