Clojure 전동 공구 2부



소개



이것은 내 Clojure Power Tools 시리즈의 두 번째 부분입니다(이 시리즈에 얼마나 많은 블로그 게시물을 작성할지 약간 관심이 있습니다). 첫 번째 부분을 읽지 않았다면 먼저 읽는 것이 좋습니다: Clojure Power Tools Part 1 . 이 두 번째 블로그 기사에서는 디버깅을 위한 몇 가지 새로운 강력한 도구 트릭을 나열합니다. 먼저 가난한 사람의 디버그 repl을 소개한 다음 실제 디버그 repl을 소개합니다.

Poor Man's Debug Repl



복잡한 애플리케이션의 두 번째 버전에 대한 일부 Clojure 테스트를 리팩토링하고 있었습니다. 애플리케이션 로직에 구조적 변화가 적지 않았고 도메인이 다양한 재귀적 데이터 구조로 구성되어 다소 복잡했습니다. 일부 테스트에서는 응용 프로그램의 여러 위치에 어떤 상태가 있는지 상당히 당황했습니다. 테스트는 또한 다소 복잡했으며 테스트의 특정 영역을 실행할 때 응용 프로그램의 여러 위치에서 특정 바인딩을 기록하는 간단한 방법을 원했습니다. 가난한 사람의 디버그 레코더를 신속하게 구현했습니다.

(ns recorder)

(def value (atom {}))
(def counter (atom 0))
(def flag (atom false))

(defn next-id []
  (swap! counter inc))

(defn assoc-value-with-id! [k v]
  (let [id (next-id)
        new-k (keyword (str (name k) "-" id))]
    (swap! value assoc new-k v)))

(defn add-value-if-recording! [k v]
  (when @flag
    (assoc-value-with-id! k v)))

(defn start! []
  (reset! value {})
  (reset! counter 0)
  (reset! flag true))

(defn stop! []
  (reset! flag false))



아이디어는 고유 키를 사용하여 값 맵에 항목을 추가하는 방법을 제공하는 것입니다. 하지만 녹음할 때만 가능합니다.

(나는 여기서 예제로 내 자신의 연습을 사용하고 있습니다. 여기의 데이터는 엄청나게 간단합니다. 여기에는 레코더가 필요하지 않지만 데이터를 수백 줄의 재귀 맵 및 벡터로 변경하고 복잡한 비즈니스 로직…)

따라서 관심 있는 테스트에 기록 시작/중지를 추가해 보겠습니다.

(deftest product-groups-test
  (log/debug "ENTER product-groups-test")
  (testing "GET: /api/product-groups"
    (let [_ (re/start!)
          login-ret (ss-tc/-call-api :post "login" nil {:email "[email protected]" :password "Kari"})
          _ (log/debug (str "Got login-ret: " login-ret))
          json-web-token (get-in login-ret [:body :json-web-token])
          params (-create-basic-authentication json-web-token)
          get-ret (ss-tc/-call-api :get "/product-groups" params nil)
          status (:status get-ret)
          body (:body get-ret)
          right-body {:ret "ok", :product-groups {:1 "Test-Books", :2 "Test-Movies"}}
          _ (re/stop!)]
      (is (= (not (nil? json-web-token)) true))
      (is (= status 200))
      (is (= body right-body)))))



테스트에서 (re/start!)(re/stop!) 명령을 참조하십시오. 해당 시간 동안에만 기록합니다.

그런 다음 내가 원하는 곳이면 어디든지 내 레코더에 항목을 추가할 수 있습니다.

(defn -valid-token?
  "Parses the token from the http authorization header and asks session ns to validate the token."
  [env req]
  (log/debug "ENTER -valid-token?")
  (let [basic (get-in req [:headers "authorization"])
        _ (re/add-value-if-recording! :valid-token-basic basic)
        basic-str (and basic (last (re-find #"^Basic (.*)$" basic)))
...



즉. (re/add-value-if-recording! :valid-token-basic basic) .

테스트를 실행합니다.

테스트 후 내 스크래치 파일에서 레코더를 검사할 수 있습니다.

  (require '[recorder])
  (keys @recorder/value)
  @recorder/value
  (require '[portal.api :as portal-api])
  (portal.api/clear)
  (portal.api/open)
  (portal.api/tap)
  (tap> @recorder/value)



또한 우수한portal 시각화 도구를 사용하여 기록한 복잡한 데이터를 검사할 수 있습니다(이 예에서는 그리 복잡하지 않음).



실제 디버그-Repl



위의 예는 간단한 트릭이지만 실제 Clojurian은 단순히 기록하는 대신 특정 순간에 무슨 일이 일어나고 있는지 보는 데 관심이 있다면 세상을 멈춥니다. 이를 위해 Gary Fredericksdebug-repl의 라이브러리를 사용할 것입니다. 종속성이 필요합니다. 제 ~/.clojure/deps.edn 파일에 다음과 같은 도구 종속성이 있습니다.

{
 :aliases {
           :kari {:extra-paths ["scratch"]
                  :extra-deps {hashp/hashp {:mvn/version "0.1.1"}
                               com.gfredericks/debug-repl {:mvn/version "0.0.11"}
                               djblue/portal {:mvn/version "0.6.1"}
                               }
                  }
           }
 }



그런 다음 이 디버그 repl 미들웨어로 백엔드 REPL을 시작할 수 있어야 합니다. 저는 이것을 다양한 옵션으로 백엔드 repl을 시작하는 데 사용하는 Just 레시피로 내Justfile에 있습니다.

# Start backend repl with my toolbox and with debug-repl capability.
@backend-debug-kari:
    clj -M:dev:test:common:backend:kari -m nrepl.cmdline -m com.gfredericks.debug-repl/wrap-debug-repl -i -C



그런 다음 코드에 debug-repl 중단점을 추가하고, 코드를 실행하고, 세계를 중지하고 중단점 직전 세계의 스냅샷 컨텍스트를 검사할 수 있습니다. 이것을 실제로 봅시다:



테스트 중 하나에 중단점_ (break! "Yihaa!")을 추가했습니다. 그런 다음 테스트를 실행하면 중단점(REPL 출력 창에 Hijacking repl for breakpoint: Yihaa! 출력)에서 세상이 멈춥니다. 그런 다음 다양한 let-bindings(json-web-token , paramsget-ret )에서 커서를 이동하고 양식을 평가했습니다. 오른쪽의 REPL 출력 창에서 평가된 값을 볼 수 있습니다. 평가하려고 하면status "Unable to resolve symbol: status in this context"오류가 발생합니다. 물론 컨텍스트 외부에 있기 때문입니다.

결론



다른 많은 Clojure 트릭과 도구가 있습니다. 나중에 "Clojure Power Tools Part 3"블로그 게시물을 작성하겠습니다.

작가는 클라우드 프로젝트에서 Clojure를 사용하여 Metosin에서 작업하고 있습니다. 핀란드에서 Clojure 프로젝트를 시작하는 데 관심이 있거나 핀란드에서 Clojure 교육을 받는 데 관심이 있는 경우 Metosin 이메일 주소로 이메일을 보내거나 LinkedIn을 통해 저에게 연락할 수 있습니다.

카리 마르틸라
  • Kari Marttila의 LinkedIn 홈 페이지:
  • 좋은 웹페이지 즐겨찾기