Clojure has this handy way to view a function's definition in REPL.
Is there one in Elixir REPL ?
No, there isn't a convenient way yet.
Well, I'm going to post this as an answer, even though it's not the same as "source". In IEX, you can type h function_name to see the documentation for function_name. It's basically Clojure REPL's doc feature. So far, in Elixir, this is good enough for most cases where I want source.
G'day gurus,
I've written some code that leverages a Java library that makes uses of the visitor pattern. What I'd like is to hide all the messy details of the visitor etc. behind a single Clojure function that takes the input parameter(s) and returns a simple data structure containing all of the state derived by the visitor.
The trick is that there are multiple "visitXXX" callbacks on the Java side and there's no easy way to return state back out of them (Java, being Java, assumes any state that gets built up by the various visitors is stored in instance variables).
What I've done (and which seems to work great, fwiw) is define an atom in a let block, and have each of my visitor functions swap! the atom with an updated value when they're called by the Java visitation code. I then return the deref'ed atom out the end of the main "driver" function, after the Java visitor completes.
My question is: is this an appropriate usage of an atom? If not, is there a more idiomatic way to do this?
If anyone's interested, the code in question is here.
Disclaimer: I'm still a Clojure n00b so that code is probably hideous to the more discerning eye. Comments / feedback / critiques welcome!
Thanks in advance!
Your approach using an atom is fine and looks good and clojurish.
If you are looking for other approaches as well; since you can split your problem into some code that will produce and answer (your visitor) and some other code that will need the answer when it is available, Clojure's promise and deliver functions may be well suited.
If you create the promises in the let block, then have the visitor deliver the results to the promise.
Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 4 years ago.
Improve this question
Both look reasonably good. I'd like to understand what each library is particularly good at or lacking, especially for testing of web applications.
I haven't used speclj, and I was the first author of Midje. One point that hasn't been mentioned by others is that Midje tries to exploit differences between functional and object-oriented languages.
One difference is immutability. Because most functions depend only on their inputs, not on contained state, the kind of truth statements you make about them are different in feel than their object-oriented counterparts. In OO testing, you make examples of the form: "given this history and these inputs, this method produces such and so."
It would seem that examples in a functional language would just be simpler ones: "given these inputs, this function returns such and so". But I don't think that's quite right. I think the other functions in the system play a role analogous to state/history: they're one of the things you're trying to get intellectual control over. Functions and their relationships are the things you want the tests to help you think clearly about.
For that reason, Midje is written under the assumption that a sweet development process involves saying:
What do I want to be true of this function? In the world of the system, what's a good way to think of what this function does?
In the process of doing that, what other functions would be useful---would capture an important part of the domain---and what truth statements do I want to make about them?
And then, in typical mockist style, you develop roughly top-down or outside-in, allowing for the inevitable iteration as you recover from mistakes or have better ideas.
The end result is to be a big pile of functions, with their interrelationships documented by the tests or (as Midje calls them) the "facts" about functions and the functions they depend on. Various people have commented that Midje has a Prolog/logic programming feel to it, and that's not an accident. As always, tests are examples, but Midje tries to make them read more like truth statements. That's the justification for its only actually innovative feature, metaconstants. Here's an example of them:
(fact "right changes the direction, but not the position"
(right (snapshot north ...position...)) => (snapshot west ...position...)
(right (snapshot east ...position...)) => (snapshot north ...position...)
(right (snapshot south ...position...)) => (snapshot east ...position...)
(right (snapshot west ...position...)) => (snapshot south ...position...))
In this case, the actual position is irrelevant to what's true about the function right, except that it never changes. The idea of a metaconstant is that it is a value about which nothing is known except what's explicitly stated in the test. Too often in tests, it's hard to tell what's essential and what's incidental. That has a number of bad effects: understanding, maintainability, etc. Metaconstants provide clarity. If it matters that a value is a map or record that contains the value 3 for key :a, you say that explicitly:
(fact
(full-name ..person..) => "Brian Marick"
(provided
..person.. =contains=> {:given-name "Brian", :family-name "Marick"}))
This test is explicit about what matters about people---and also explicit about what doesn't matter (anything but the two names).
In math terms, Midje is trying to let you make statements like "for all x where x..." while still being a test tool rather than a theorem prover.
This approach was inspired by "London-style" mock-heavy TDD of the sort described in Growing Object-Oriented Software, which is the approach I usually use in writing Ruby code. But it's turned out to have a pretty different feel, in a way that's hard to describe. But it's a feel that needs more tool support than just with-redefs.
The upshot is that Midje is in part an attempt to find a style of functional TDD that's not just a port of OO TDD. It tries to be a general-purpose tool, too, but it's semi-opinionated software. As Abraham Lincoln said, "Those who like this sort of thing will find this the sort of thing they like."
The biggest benefit of using Midje is that it provides focused abstractions for testing things without testing all of their parts, parts that often drag in the whole rest of the world.
If you have a function that involves calling a subsidiary function to generate a timestamp, putting something in a database or message queue, make an API request, caching something, logging something, etc, you want know that these world-involving function calls occurred (and sometimes how many times they occurred), however actually executing them is irrelevant to the function you are testing, and the called functions will often deserve having their own unit tests.
Say you have this in your code:
(defn timestamp [] (System/currentTimeMillis))
(defn important-message [x y] (log/warnf "Really important message about %s." x))
(defn contrived [x & y]
(important-message x y)
{:x x :timestamp (timestamp)})
Here is how you could test it with midje:
(ns foo.core-test
(:require [midje.sweet :refer :all]
[foo.core :as base]))
(fact
(base/contrived 100) => {:x 100 :timestamp 1350526304739}
(provided (base/timestamp) => 1350526304739
(base/important-message 100 irrelevant) => anything :times 1))
This example is just a quick glimpse at what you can do with midje but demonstrates the essence of what it is good at. Here you can see there is very little extraneous complexity needed to express:
what the function should produce (despite the fact that what the
timestamp function would produce would be different each time you
call the function),
that the timestamp function and the logging function were called,
that the logging function was only called one time,
that the logging function received the expected first argument, and
that you don't care what the second argument it received was.
The main point I am trying to make with this example is that it's a very clean and compact way of expressing tests of complex code (and by complex I mean it has embedded parts that can be separated) in simple pieces rather than trying to test everything all at once. Testing everything all at once has its place, namely in integration testing.
I am admittedly biased because I actively use midje, whereas I have only looked at speclj, but my sense is that speclj is probably most attractive to people who have used the analogous Ruby library and find that way of thinking about tests ideal, based on that experience. That is a perfectly rspectable reason to chose a testing framework, and there are probably other nice things about it as well that hopefully others can comment on.
I'd definitely go with Speclj.
Speclj is simple to integrate and use. Its syntax is less flamboyant than Midje's. Speclj is based on RSpec to give you all the conforts that Ruby programmers are used to without losing the idiosyncrasies of Clojure.
And the auto runner in Speclj is great.
lein spec -a
Once you've used that for a while, you'll wonder how you ever got work done when you had to manually run tests.
Mocking is a non-issue since you can simply use with-redefs. #rplevy's example in Speclj would look like this.
(ns foo.core-spec
(:require [speclj.core :refer :all ]
[foo.core :as base]))
(describe "Core"
(it "contrives 100"
(let [message-params (atom nil)]
(with-redefs [base/timestamp (fn [] 1350526304739)
base/important-message #(reset! message-params [%1 %2])]
(should= {:x 100 :timestamp 1350526304739} (base/contrived 100))
(should= 100 (first #message-params))))))
This bare-bones approach to mocking is to-the-point; no misdirection.
As for testing web apps, Speclj works fine. In fact Speclj support is build into Joodo.
disclaimer: I wrote Speclj
I'd say that Midje is especially good at creating a DSL for expressing stubbing and mocking. If you care about stubbing and mocking, and want to use it a lot, I'd choose Midje over Speclj, because it has abstractions for expressing those types of tests that are more concise than the approach slagyr offered in his answer.
Another option, if you want a more light-weight approach, is the Conjure stubbing/mocking library intended to be used with clojure.test.
Where Speclj shines is in being a lot like RSpec, having 'describe' and 'it' included... Midje can support nested facts actually, but not as elegantly as Speclj.
disclaimer: I'm a contributor to Midje and Conjure. :)
I would suggest Midje over Speclj
For speclj, I don't think if it has good support for mocks, the documentation also looks sparse as compared to Midje.
Also the syntax for Midje is better:
(foo :bar) => :result compared to (should= (foo :bar) :result)
I'm at loss of how to create a Java enum in Clojure. I want to create a Java enum that uses a Java interface and then pass it into a Java method, all within Clojure. I want to do this to work with the neo4j graph library (I don't want to use someone's prebuilt interface, I want to write my own interop code).
I searched around the internet, and it looks like I can use the proxy method, but I can't for the life of me get it to work. Here's the equivalent Java code I need to write in Clojure:
private static enum RelTypes implements RelationshipType
{
KNOWS
}
And here's my stab at it (It's not right :( ):
(proxy [org.neo4j.graphdb.RelationshipType] [] (KNOWS))
I'm also wondering if there's a good website that documents things like this that I'm missing. I know about the Clojure docs on the Clojure site, which is really useful, but for example of usage I can't always find what I need. Perhaps I need a good reference book?
Why not just create the enum in Java? Sometimes falling back to Java is the simplest answer.
Here is a very old thread about using proxy to define enums from Rich Hickey and Stuart Sierra along with some alternatives using gen-class. I think the proxy path should work with something like this for you:
(proxy [Enum org.neo4j.graphdb.RelationshipType] [ "KNOWS" 1 ])
But that won't generate anything you'd want an external Java user to use, in which case gen-class is likely the better solution.
Upgrading to Clojure 1.3, I need to replace some binding-based mocks with 1.3-friendly mocking. The mock library seems to be useful for replacing instances where I was formerly using binding to mock a function call within a function I'm unit testing, however there are some cases where what I want to mock is a var that is bound to some data. What would be a good way to do this in Clojure 1.3?
with-redefs was introduced for the same purpose in Clojure-1.3.