Передача переменных между протестами в модульных тестах Clojure - PullRequest
0 голосов
/ 08 октября 2018

Я пытаюсь написать несколько юнит-тестов, чтобы протестировать некоторые модели БД.

Я бы хотел, чтобы моя первая функция deftest захватила сгенерированный db идентификатор вставленного пользователя, сохранила его где-нибудь, чтобы следующий deftest мог получить этого же пользователя из db.

Я думал, что смогу сделать это, используя def в первом испытании, но определенный вар считается непокрытым переменным во втором испытании.Вот мой код:

(deftest test-user->db
  (testing "Adding a new user record to db"
    (->> (user->db {:name "Bob"})  ;; returns a UUID ID
         (def mock-user-id))       ;; binding it here
    (is (uuid? mock-user-id))))    ;; this passes

(deftest test-db->user
  (testing "Getting a user record from db"
    (let [user (db->user mock-user-id)] ;; mock-user-id is unbound :-/
      (is (instance? User user))
      (is (contains? user :id))
      (is (contains? user :name))
      (is (= mock-user-id (:id user)))
      (is (= "Bob" (:name user))))))

К сожалению, я не могу найти никаких ресурсов, почему это так.Я могу только предположить, что каким-то образом глобальные переменные пространства имен сбрасываются для каждого deftest?

Ответы [ 2 ]

0 голосов
/ 09 октября 2018

Я хотел бы добавить к ответу @ carcigenicate выше, на случай, если кто-то еще наткнется на эту тему и захочет запустить определенные тестовые функции последовательно (поскольку по умолчанию они не работают по порядку).

В отдельных тестах создайте функцию с именем test-ns-hook и вызовите ваши тестовые функции в том порядке, в котором вы хотите, чтобы они выполнялись.Если test-ns-hook определен в ns, тестовый исполнитель просто запустит эту функцию вместо всех определенных тестов в этом ns.

Так что в моем вопросе я добавил эту функцию в концефайл:

(defn test-ns-hook []
  (test-user->db)
  (test-db->user))

Это гарантирует, что test-user->db сначала запускается и завершается, связывает переменную, затем test-db->user запускается с этой переменной.

0 голосов
/ 08 октября 2018

Очевидно, что тесты не обязательно выполняются по порядку:

(deftest a-test
  (println "a")
  (def inner "hello"))

(deftest b-test
  (println "b")
  (println "inner" inner))

Testing tic-tac-toe.core-test
b
inner #object[clojure.lang.Var$Unbound 0x37acbc9e Unbound: #'tic-tac-toe.core-test/inner]
a

Ran 2 tests containing 0 assertions.
0 failures, 0 errors.
=> {:test 2, :pass 0, :fail 0, :error 0, :type :summary}

Обратите внимание, как сначала печатается буква "b".Это означает, что ваша переменная не могла быть инициализирована к тому времени, когда она была необходима.

Я бы исправил это, объявив mock-user-id верхнего уровня, а затем использовал бы его в обоих тестах, чтобы порядок испытаний не имел значения.Вы можете обернуть его в delay, если не хотите, чтобы он инициализировался до тех пор, пока он абсолютно не понадобится:

; delay will delay initialization until it's first used
(def mock-user-id (delay (user->db {:name "Bob"})))

(deftest test-user->db
  (testing "Adding a new user record to db"
    (is (uuid? @mock-user-id)))) ; @ to force the delay to run its body the first time

(deftest test-db->user
  (testing "Getting a user record from db"
    (let [user (db->user @mock-user-id)] ;; mock-user-id is unbound :-/
      (is (instance? User user))
      (is (contains? user :id))
      (is (contains? user :name))
      (is (= @mock-user-id (:id user)))
      (is (= "Bob" (:name user))))))
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...