DZone
Thanks for visiting DZone today,
Edit Profile
  • Manage Email Subscriptions
  • How to Post to DZone
  • Article Submission Guidelines
Sign Out View Profile
  • Post an Article
  • Manage My Drafts
Over 2 million developers have joined DZone.
Log In / Join
Refcards Trend Reports Events Over 2 million developers have joined DZone. Join Today! Thanks for visiting DZone today,
Edit Profile Manage Email Subscriptions Moderation Admin Console How to Post to DZone Article Submission Guidelines
View Profile
Sign Out
Refcards
Trend Reports
Events
Zones
Culture and Methodologies Agile Career Development Methodologies Team Management
Data Engineering AI/ML Big Data Data Databases IoT
Software Design and Architecture Cloud Architecture Containers Integration Microservices Performance Security
Coding Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks
Partner Zones AWS Cloud
by AWS Developer Relations
Culture and Methodologies
Agile Career Development Methodologies Team Management
Data Engineering
AI/ML Big Data Data Databases IoT
Software Design and Architecture
Cloud Architecture Containers Integration Microservices Performance Security
Coding
Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance
Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks
Partner Zones
AWS Cloud
by AWS Developer Relations
  1. DZone
  2. Coding
  3. Java
  4. Clojure libraries and builds with Leiningen

Clojure libraries and builds with Leiningen

Giorgio Sironi user avatar by
Giorgio Sironi
·
Dec. 27, 11 · Interview
Like (0)
Save
Tweet
Share
7.32K Views

Join the DZone community and get the full member experience.

Join For Free

Leiningen is an automation tool for Clojure projects: while you could in theory continue to use Ant and Maven directly to download JARs dependencies and to run tasks such as the project's test suite, Leiningen allows you to write just Clojure code, and generate on the fly everything else.

In short, Leiningen will use Ant and Maven under the covers, and follow the Maven model of downloading and caching dependencies globally instead of storing them along with your source code. But you won't see under the hood.

Installation

Assuming you're using a Linux system like Ubuntu and the shipped Clojure copy, installing the leiningen package will bring you the lein command.

Alternatively, you can download a single script from the bin/folder, place it on your path and make it executable. On the first execution it will bootstrap itself by downloading the missing dependencies.

There are also installation instruction for Windows boxes, both for the self-installing version and a standalone one.

A walkthrough: creating a new project

Leiningen can create a simple skeleton for our project:

[08:37:53][giorgio@Desmond:~/code]$ lein new clojure-midje-example
Created new project in: /home/giorgio/code/clojure-midje-example
[08:38:01][giorgio@Desmond:~]$ cd code/clojure-midje-example
[08:38:29][giorgio@Desmond:~/code/clojure-midje-example]$ tree
.
├── project.clj
├── README
├── src
│   └── clojure_midje_example
│       └── core.clj
└── test
    └── clojure_midje_example
        └── test
            └── core.clj

5 directories, 4 files

We see a test and src folder, in the best Java/JVM tradition. The source file created as examples follow the folder structure as namespaces:

[09:00:17][giorgio@Desmond:~/code/clojure-midje-example]$ cat test/clojure_midje_example/test/core.clj
(ns clojure-midje-example.test.core
  (:use [clojure-midje-example.core])
  (:use [clojure.test]))

(deftest replace-me ;; FIXME: write
  (is false "No tests have been written."))

You can already try to execute the failing test:

[09:02:52][giorgio@Desmond:~/code/clojure-midje-example]$ lein test
Copying 1 file to /home/giorgio/code/clojure-midje-example/lib
Testing clojure-midje-example.test.core
FAIL in (replace-me) (core.clj:6)
No tests have been written.
expected: false
  actual: false
Ran 1 tests containing 1 assertions.
1 failures, 0 errors.

And of course, write a real test:

[09:05:05][giorgio@Desmond:~/code/clojure-midje-example]$ cat test/clojure_midje_example/test/core.clj
(ns clojure-midje-example.test.core
  (:use [clojure-midje-example.core])
  (:use [clojure.test]))

(deftest the-simplest-test-you-can-write
  (is 3 (+ 1 2)))
[09:05:08][giorgio@Desmond:~/code/clojure-midje-example]$ lein testTesting clojure-midje-example.test.core
Ran 1 tests containing 1 assertions.
0 failures, 0 errors.

Leiningen also produces a .gitignore file that allows you to ignore compiled classes, any kind of JAR, generated XML and Leiningen's own metadata.

Installing a library: Midje

Midje is a testing framework for Clojure, that I want to install both for being able to try it out later and for demonstrating how Leiningen can pull in a library.

The project.clj file contains all the definitions of dependencies that Leiningen will use to grab JARs. The format of :dependencies is a list of 2-element lists, where each 2-element list contains the name of the library and the required version as a string.

[09:06:11][giorgio@Desmond:~/code/clojure-midje-example]$ cat project.clj
(defproject clojure-midje-example "1.0.0-SNAPSHOT"
  :description "FIXME: write description"
  :dependencies [[org.clojure/clojure "1.2.1"]])

By default, Leiningen will grab packages from Clojars, the main community repository for Clojure libraries, and from Maven Central.

Let's fix our project.clj to include midje and midje-lein, two JARs that will make Midje available to the current project. The first is the actual library, while the second provides the lein midje command, a nicer version of lein test.

[09:12:52][giorgio@Desmond:~/code/clojure-midje-example]$ cat project.clj
(defproject clojure-midje-example "1.0.0-SNAPSHOT"
  :description "FIXME: write description"
  :dependencies [[org.clojure/clojure "1.2.1"]
                 [midje "1.3.0"]]
  :dev-dependencies [[lein-midje "1.0.7"]])

I put midje in :dependencies just to show a different option for libraries, but it should actually be put in :dev-dependencies. The difference is in the latter case it won't be shipped in the JAR package of the project, nor being pulled into projects that depend on the current one.

To validate the availability of midje, let's write the simplest midje test:

[09:17:04][giorgio@Desmond:~/code/clojure-midje-example]$ cat test/clojure_midje_example/test/core.clj
(ns clojure-midje-example.test.core
  (:use [clojure-midje-example.core])
  (:use [clojure.test])
  (:use [midje.sweet]))

(deftest the-simplest-test-you-can-write
  (is 3 (+ 1 2)))
(fact (+ 1 2) => 3)
[09:16:55][giorgio@Desmond:~/code/clojure-midje-example]$ lein midje>>> clojure.test summary:
Ran 1 tests containing 1 assertions.
0 failures, 0 errors.
>>> Midje summary:
All claimed facts (1) have been confirmed.

More lein commands

I have posted this example on Github, both for your and mine future reference.

For the ones of you that don't come from a JVM background, don't try to run .clj files in isolation: lein should always be used as a wrapper for him to be able to place the dependencies on the classpath.

Lein provides many other commands for this goal; for example:

  • lein run will call the -main function in the namespace defined with :main in project.clj (it's easy to show than to explain: see the source code.)
  • lein help run will display information about the run command; substitute your favorite command to learn all its options and how it interacts with project.clj.
  • lein jar and lein uberjar will produce a JAR and a standalone JAR respectively for distributing your code.

Conclusions

You don't see it in this output sample, but lein midje also provides colors (a green bar), since it is a custom Leiningen task. The actual usage of Midje is out of the scope of this article, but I hope to have provided a simple way to grab dependencies inside your project.

Lein is easy to use, and provides enough documentation for basic use cases; in integrates testing as a first class task. However error messages are somewhat cryptic, and this is typical of Clojure: make sure to take small steps in order to easily locate any error in the last lines you wrote.

Leiningen (software) Clojure Library

Opinions expressed by DZone contributors are their own.

Popular on DZone

  • Getting a Private SSL Certificate Free of Cost
  • The Beauty of Java Optional and Either
  • DeveloperWeek 2023: The Enterprise Community Sharing Security Best Practices
  • 5 Common Firewall Misconfigurations and How to Address Them

Comments

Partner Resources

X

ABOUT US

  • About DZone
  • Send feedback
  • Careers
  • Sitemap

ADVERTISE

  • Advertise with DZone

CONTRIBUTE ON DZONE

  • Article Submission Guidelines
  • Become a Contributor
  • Visit the Writers' Zone

LEGAL

  • Terms of Service
  • Privacy Policy

CONTACT US

  • 600 Park Offices Drive
  • Suite 300
  • Durham, NC 27709
  • support@dzone.com
  • +1 (919) 678-0300

Let's be friends: