Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

clojure read-line fails inside leiningen test

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)))))
like image 661
Roger Allen Avatar asked Nov 04 '22 16:11

Roger Allen


1 Answers

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.

like image 105
DaoWen Avatar answered Nov 13 '22 04:11

DaoWen