2013-04-08 12 views
11

Clojureでいくつかのテストを書こうとしています。これらのテストの1つは、実行中のテストファイルと同じディレクトリにhtmlファイルを開いて、その内容をテスト入力(Pythonで広く使われているイディオム)として使用することです。私は*file* varが仕事をすると思っていましたが、それは相対的なので実際にはそうではありません。Clojureで実行中のコードと同じディレクトリにファイルをオープン

デフォルトのleiningenレイアウトを使用する私のプロジェクトは、demoprojと呼ばれています。私のテストは~/projects/demoproj/testです。このディレクトリは、プロジェクトの名前空間を再度複製します。これは私が大好きではありませんが、何でも構いません。したがってcore.cljのテストは~/projects/demoproj/test/demoproj/test/core.cljにあります。同じディレクトリにsmall_page.htmlというファイルもあります。私はtest/core.cljに次のように置く場合:

(println (-> (java.io.File. *file*) 
      .getPath)) 

をここに私が得るものです:

demoproj/test/readibility.clj 

これは、プロジェクトベースのtestディレクトリに対する相対パスです。次のように私は、これだけの相対パスを使用してサンプルHTMLページを読んでみました:

(slurp (-> (java.io.File. *file*) 
      .getParent 
      (java.io.File. "small_page.html") 
      .getPath)) 

ファイルがその場所に読み取ることができないので、これはIOエラーが発生します。私の次のアイデアは、現在の作業ディレクトリを取得し、それを相対パスと結合することでした。ここで私は作業ディレクトリをフェッチする方法である:

絶対パスを返さ
(println (-> (java.io.File. ".") 
      .getCanonicalPath)) 

/Path-to-home/projects/demoproj 

悪いことでは、これら2つのファイルへの正しいパスに加入していない、です。その間にtestコンポーネントがありません。これらの2つのパスに参加すると、不正なディレクトリパスが発生します。

私の質問は、現在実行されているコードファイルの絶対パスを取得する信頼できる方法ですか?これが不可能な場合、このイディオムの代替手段は何でしょうか。つまり、テストファイルに関連する場所にあるファイルをどのように解析できますか?

答えて

16

clojureコードと関連リソースはjarで終わる可能性があり、アクセスしているファイルが実際のファイルシステムではなくjarの一部として終了してもコードを実行したい場合は、 io/resourceを使用し、問題のファイルがresource-pathにあることを確認してください。

例えば、私は現在のプロジェクトで私のディレクトリ構造の一部として、以下があります。

|-- project.clj 
|-- resources 
| |-- caribou.properties 
| |-- config 
| | |-- boot.clj 
| | |-- development.clj 
| | |-- local-dumped.clj 
| | |-- local.clj 
| | |-- production.clj 
| | |-- staging.clj 
| | `-- test.clj 
| `-- logging.properties 

私は私のプロジェクトで、次のようしています。CLJ:

:resource-paths ["shared" "resources"] 

その後、私は私のREPLで、次の操作を行うことができます。あなたが見ることができるよう

user> (do (require '[clojure.java.io :as io]) (io/resource "config/boot.clj")) 
#<URL file:/Users/me/this-project/resources/config/boot.clj> 
user> (slurp *1) 
"(use '[caribou.config :only (read-config configure environment)])\n(require '[clojure.java.io :as io])\n..." 

、IO /リソースは私が、私が求めるファイルを読まに渡すことができるURLを返します。 (設定されたリソースパス内のパスフラグメントを参照)。このコードは、アプリケーション全体が展開のためにuberjarにラップされ、io /ファイルを作成してgetParentを呼び出すのが失敗する場合にも機能します。

2

私はもう少しグーグルグーグルでこれを行う方法を理解し、実際にはStackoverflowですべての答えを読んでいます。 user83510は実際に質問https://stackoverflow.com/a/11498784/1285782に答えましたが、回答は受け入れられなかったか、適切にアップvotedされていませんでした。

(-> (ClassLoader/getSystemResource *file*) clojure.java.io/file .getParent) 

これはあなたのディレクトリへの絶対パスを与える:トリックは以下の通りです。美しくはないが働く。

関連する問題