/
testing.clj
115 lines (105 loc) · 4.23 KB
/
testing.clj
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
(ns lambdakube.testing
(:require [lambdakube.core :as lk]
[clojure.java.shell :as sh]
[clojure.data.json :as json]
[clojure.data.xml :as xml]
[clojure.string :as str]))
(defn test [$ test config deps func]
(let [func' (fn [run-this-test & args]
(-> (apply func args)
(update :metadata assoc :name :test)
(lk/job :Never {:backoffLimit 0})))]
(-> $
(update :tests assoc test config)
(lk/rule test (vec (cons (keyword (str "run-" (name test))) deps)) func'))))
(defn- kubectl [& args]
(let [ret (apply sh/sh "kubectl" args)]
(when-not (= (:exit ret) 0)
(throw (Exception. (:err ret))))
(:out ret)))
(defn log [msg]
(println msg))
(defn run-test [$ test prefix]
(let [kns (str prefix "-" (name test))
test-config (-> ((:tests $) test)
(assoc (keyword (str "run-" (name test))) true))
depl (lk/get-deployable $ test-config)
yaml (lk/to-yaml depl)
filename (str kns ".yaml")]
(spit filename yaml)
(log (str "Creating namespace " kns))
(kubectl "create" "ns" kns)
(log (str "Deploying test " test))
(kubectl "-n" kns "apply" "-f" filename)
(let [status (loop []
(let [out (kubectl "-n" kns "get" "job" "test" "-o" "json")
job (json/read-str out)
status (job "status")]
(if (and (contains? status "active")
(> (status "active") 0))
(recur)
;; else
(if (and (contains? status "succeeded")
(> (status "succeeded") 0))
:pass
;; else
:fail))))
joblog (kubectl "-n" kns "logs" "-ljob-name=test")]
(log (str "Test " test " completed. Status: " status))
(when (= status :pass)
(log (str "Deleting namespace " kns))
(kubectl "-n" kns "delete" "-f" filename)
(kubectl "delete" "ns" kns))
{:log joblog
:status status})))
(defn run-tests
([$ prefix]
(run-tests $ prefix (constantly true)))
([$ prefix pred]
(->> (:tests $)
(filter (comp pred second))
(map (fn [[k v]]
[k (run-test $ k prefix)]))
(into {}))))
(defn insert-stylesheet-pi [xml index]
(str (subs xml 0 index)
"<?xml-stylesheet href=\"https://raw.githubusercontent.com/xunit/xunit/master/src/xunit.console/HTML.xslt\"?>"
(subs xml index)))
(defn to-xunit [res filename]
(let [passed (->> res
(map second)
(filter #(= (:status %) :pass))
(count))
failed (->> res
(map second)
(filter #(= (:status %) :fail))
(count))
xml (xml/sexp-as-element [:assemblies
[:assembly {:name "lambda-kube tests"
:passed passed
:failed failed}
(vec (concat [:collection {:name "tests"
:passed passed
:failed failed}]
(for [[k v] res]
[:test {:name (name k)
:result (if (= (:status v) :pass)
"Pass"
;; else
"Fail")}])))]])
xmlstr (xml/indent-str xml)
index (+ (str/index-of xmlstr "?>") 2)
xmlstr (insert-stylesheet-pi xmlstr index)]
(spit filename xmlstr))
nil)
(defn kube-tests
([$ prefix]
(kube-tests $ prefix (constantly true)))
([$ prefix pred]
(let [res (run-tests $ prefix pred)]
(to-xunit res (str prefix "-results.xml"))
(->> res
(map (fn [[k v]] (assoc v :log (str "Test " k "\n" (:log v) "\n==="))))
(filter #(= (:status %) :fail))
(map :log)
(reduce str "")))))