Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
refactoring namespaces, and add nicer console reporter
- Loading branch information
Alfred Xiao
committed
Aug 5, 2019
1 parent
fc95ff1
commit 9cd9978
Showing
4 changed files
with
92 additions
and
75 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,89 +1,27 @@ | ||
(ns canvas.core | ||
(:require [clojure.test] | ||
[clojure.string :refer [starts-with? ends-with?]] | ||
[clojure.tools.namespace.find :as ns-find] | ||
[clojure.pprint :refer [pprint]] | ||
[clojure.java.io :as io])) | ||
|
||
(defn- log-info [& msgs] | ||
#_(apply println msgs)) | ||
|
||
(defn- instrument | ||
[f v] | ||
(fn [& args] | ||
(alter-meta! v assoc ::tested? true) | ||
(alter-meta! v update ::hit inc) | ||
(apply f args))) | ||
|
||
(defn- instrumentable? | ||
[v] | ||
(and (.isBound v) | ||
(fn? @v) | ||
(not (:macro (meta v))) | ||
(not (:test (meta v))))) | ||
|
||
(defn instrument-var! [v] | ||
(when (instrumentable? v) | ||
(log-info "canvas: instrumenting function " v) | ||
(alter-meta! v assoc ::tested? false) | ||
(alter-meta! v assoc ::hit 0) | ||
(alter-meta! v assoc ::original @v) | ||
(alter-var-root v instrument v))) | ||
|
||
(defn uninstrument-var! [v] | ||
(when (instrumentable? v) | ||
(let [root (::original (meta v))] | ||
(assert root "No root binding to restore!") | ||
(alter-meta! v dissoc ::tested?) | ||
(alter-meta! v dissoc ::hit) | ||
(alter-meta! v dissoc ::original) | ||
(alter-var-root v (constantly root))))) | ||
|
||
(defn apply-to-each-var [f ns] | ||
(doseq [[_ v] (ns-interns ns)] | ||
(f v))) | ||
|
||
(defn instrument-ns! [& nz] | ||
(doseq [n nz] | ||
(log-info "canvas: instrumenting publics of ns:" (ns-name n)) | ||
(apply-to-each-var instrument-var! n))) | ||
|
||
(defn uninstrument-ns! [& nss] | ||
(doseq [ns nss] | ||
(apply-to-each-var uninstrument-var! ns))) | ||
|
||
(defn- user? [ns] | ||
(= "user" (name (ns-name ns)))) | ||
|
||
(defn report [nz] | ||
(into {} | ||
(for [n nz :when (not (user? n))] | ||
[(ns-name n) | ||
(into {} | ||
(for [[_ v] (ns-interns n) :when (instrumentable? v)] | ||
[(:name (meta v)) (let [mt (meta v)] | ||
{:scope (if (:private mt) :private :public) | ||
:line (:line mt) | ||
:tested? (::tested? mt) | ||
:hit (::hit mt)})]))]))) | ||
[clojure.java.io :as io] | ||
[canvas.instrument :as ins] | ||
[canvas.report :refer [report]])) | ||
|
||
(defn- doseq-with [values op] | ||
(doseq [v values] | ||
(op v))) | ||
|
||
(defn evaluate-test-coverage | ||
[{:keys [source-paths test-paths] :as opts}] | ||
(let [target-nz (apply concat (->> source-paths | ||
[{:keys [source-paths test-paths reporter]}] | ||
(let [target-nss (apply concat (->> source-paths | ||
(map io/file) | ||
(map ns-find/find-namespaces-in-dir))) | ||
test-nz (apply concat (->> test-paths | ||
test-nss (apply concat (->> test-paths | ||
(map io/file) | ||
(map ns-find/find-namespaces-in-dir)))] | ||
(doseq-with target-nz require) | ||
(doseq-with test-nz require) | ||
(doseq-with target-nss require) | ||
(doseq-with test-nss require) | ||
(try | ||
(doseq-with target-nz instrument-ns!) | ||
(apply clojure.test/run-tests test-nz) | ||
(pprint (report target-nz)) | ||
(doseq-with target-nss ins/instrument-ns!) | ||
(apply clojure.test/run-tests test-nss) | ||
(report target-nss reporter) | ||
(finally | ||
(mapv uninstrument-ns! target-nz))))) | ||
(mapv ins/uninstrument-ns! target-nss))))) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,43 @@ | ||
(ns canvas.instrument) | ||
|
||
(defn- instrument | ||
[f v] | ||
(fn [& args] | ||
(alter-meta! v assoc ::tested? true) | ||
(alter-meta! v update ::hit inc) | ||
(apply f args))) | ||
|
||
(defn instrumentable? | ||
[v] | ||
(and (.isBound v) | ||
(fn? @v) | ||
(not (:macro (meta v))) | ||
(not (:test (meta v))))) | ||
|
||
(defn instrument-var! [v] | ||
(when (instrumentable? v) | ||
(alter-meta! v assoc ::tested? false) | ||
(alter-meta! v assoc ::hit 0) | ||
(alter-meta! v assoc ::original @v) | ||
(alter-var-root v instrument v))) | ||
|
||
(defn uninstrument-var! [v] | ||
(when (instrumentable? v) | ||
(let [root (::original (meta v))] | ||
(assert root "No root binding to restore!") | ||
(alter-meta! v dissoc ::tested?) | ||
(alter-meta! v dissoc ::hit) | ||
(alter-meta! v dissoc ::original) | ||
(alter-var-root v (constantly root))))) | ||
|
||
(defn apply-to-each-var [f ns] | ||
(doseq [[_ v] (ns-interns ns)] | ||
(f v))) | ||
|
||
(defn instrument-ns! [& nz] | ||
(doseq [n nz] | ||
(apply-to-each-var instrument-var! n))) | ||
|
||
(defn uninstrument-ns! [& nss] | ||
(doseq [ns nss] | ||
(apply-to-each-var uninstrument-var! ns))) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,36 @@ | ||
(ns canvas.report | ||
(:require [canvas.instrument :as ins])) | ||
|
||
(defn- user? [ns] | ||
(= "user" (name (ns-name ns)))) | ||
|
||
(defn- console [stats] | ||
(let [max-nsname-len (->> stats keys | ||
(map name) | ||
(map count) | ||
(apply max)) | ||
nsname-fmt-str (str " %s %-" (inc max-nsname-len) "s%s") | ||
max-chars-per-line (+ max-nsname-len 20)] | ||
(println (apply str (repeat max-chars-per-line "="))) | ||
(doseq [[nsname ns-stats] stats] | ||
(println nsname) | ||
(doseq [[fn-name fn-stat] ns-stats] | ||
(let [visibility-indicator (if (:private fn-stat) "-" "+") | ||
tested-indicator (if (:tested? fn-stat) "T" " ")] | ||
(println (format nsname-fmt-str visibility-indicator fn-name | ||
(format "%s %d" tested-indicator (:hit fn-stat))))))) | ||
(println (apply str (repeat max-chars-per-line "="))))) | ||
|
||
(defn report [nss reporter] | ||
(let [stats (into {} | ||
(for [n nss :when (not (user? n))] | ||
[(ns-name n) | ||
(into {} | ||
(for [[_ v] (ns-interns n) :when (ins/instrumentable? v)] | ||
[(:name (meta v)) (let [mt (meta v)] | ||
{:private (:private mt) | ||
:line (:line mt) | ||
:tested? (:canvas.instrument/tested? mt) | ||
:hit (:canvas.instrument/hit mt)})]))]))] | ||
(case reporter | ||
(console stats)))) |