5
votes

I'm testing some audio behavior and I need the user to judge if things pass or fail. I'd like to ask the user for a response within a leiningen test. But, there is something happening to read-line that prevents this.

This is some example test code after creating a new clojure project with "lein new foo" and editing the foo/test/foo/core_test.clj file:

(ns foo.core-test
  (:use clojure.test
        foo.core))

(deftest a-test
  (testing "FIXME, what a fail."
    (let [_ (println "enter something")
          yn (read-line)]
      (println yn)
      (is (= yn "y")))))

and this is what happens in a "lein test"

lein test foo.core-test
enter something
hi
there
what
is 
going on?
^C

only control-C stops the (read-line) call.

I'm using Clojure 1.4.0 and Leiningen 2.0.0-preview7 on Java 1.6.0_35 Java HotSpot(TM) 64-Bit Server VM

Any ideas on how to get read-line to work inside a test?

I should also note that (read-line) does work fine inside "lein repl" for me...

> lein repl
nREPL server started on port 54398
REPL-y 0.1.0-beta8
Clojure 1.4.0
    Exit: Control+D or (exit) or (quit)
Commands: (user/help)
    Docs: (doc function-name-here)
          (find-doc "part-of-name-here")
  Source: (source function-name-here)
          (user/sourcery function-name-here)
 Javadoc: (javadoc java-object-or-class-here)
Examples from clojuredocs.org: [clojuredocs or cdoc]
          (user/clojuredocs name-here)
          (user/clojuredocs "ns-here" "name-here")

user=> (println (read-line))
       hi
hi
nil
user=> (read-line)
       ho
"ho"

UPDATE:

I'm going to give @DaoWen the win on this. Reading the links & googling around, stdin is just b0rken on leiningen. With enough hoop-jumping, perhaps I could figure this out, but the suggestion of a dialog box seems like the best path forward. Dropping some test code here just for completeness in case this helps others.

(ns foo.core-test
  (:use clojure.test
        foo.core))

(import 'javax.swing.JOptionPane)

(defn ask-yn
  "return 0 on pass, 1 on fail"
  [prompt]
  (JOptionPane/showConfirmDialog nil prompt "User Input" JOptionPane/YES_NO_OPTION))

(deftest a-test
  (testing "a-test"
    (let [yn (ask-yn "did a-test pass?")]
      (is (= yn 0)))))

(deftest b-test
  (testing "b-test"
    (let [yn (ask-yn "did b-test pass?")]
      (is (= yn 0)))))
1
Maybe run it as lein trampoline repl?Bill
lein trampoline test results in "Tests did not finish cleanly." and no request for input. (note, lein repl already works for me)Roger Allen

1 Answers

2
votes

I know this doesn't fix your read-line issue, but maybe you can get around it by just using a JOptionPane instead. If I were a user listening to several sound files I'd rather just click Yes or No rather than having to type one of the two.

(import 'javax.swing.JOptionPane)
(JOptionPane/showConfirmDialog nil "Did the test pass?" "User Input" JOptionPane/YES_NO_OPTION)

Update:

I thought I'd seen something like this before:

Why does read-line not return after hitting ENTER (seems like a hang) using lein run, but works with lein repl?

It looks like you should try running lein trampoline test instead of just lein test in order to resolve the stdin issues.