        (some #(cyclic? deps % (conj visited x)) (deps x)))))
 
 (defn tests-from [file sheet]
-  (let [tests (->> (map #(zipmap fields %) (read-rows file sheet))
-                   (filter #(not (str/blank? (:test %))))
-                   (map #(update % :priority to-int))
-                   (map-indexed #(-> %2 (assoc :placeholders (placeholders-of %2) :id %1)
-                                     (update :extractions str->map #"\s*=\s*"))))
+  (let [tests (load-tests-from file sheet)
+        valid-tests (map #(assoc :placeholders (placeholders-of %))
+                         (remove :invalid tests))
         extractors (for [t tests :when (:extractions t)] [(:id t) (map first (:extractions t))])
         tests (map (fn [{:keys[placeholders options] :as test}]
                      (assoc test :deps (for [[i extractions] extractors

  (with-open [in-file (io/reader file)]
    (doall (rest (csv/read-csv in-file)))))

(defmethod load-tests-from :yaml [file]
  (from-yaml file))

(defn parse-options [options]

        data))
    {:error (str "missing request verb/url:" (:suite params) "/" (:name params))}))

(defn- parse-test [t]
  (-> t
      (update :priority to-int)
      (dissoc :exp-status :exp-body :exp-headers :extractors)
      (assoc :expect
             (into {} [[:status (:exp-status t)]
                       (some->> t :exp-body not-empty (vector :body))
                       (some->> t :exp-headers not-empty #(str->map % #":")
                                (vector :headers))]))
      (assoc :options
             (into (or (some-> t :options not-empty parse-options) {})
                   [[:priority (or (some-> t :priority not-empty to-int) 0)]
                    (some->> t :extractors not-empty #(str->map #"\s*=\s*") (vector :extractors))]))))

(defn- rows->test-cases
  "converts rows into test-cases"
  [rows]
  (loop [suite "(Ungrouped Tests)"
         id 0
         rows rows
         tests []]
    (if (empty? rows)
      tests
      (let [t (zipmap fields (first rows))
            suite (or (:suite t) suite)
            t (parse-test (assoc t :suite suite :id id))
            t (if (s/valid? ::rs/test-case t) t
                  (assoc t :invalid (s/explain-str ::rs/test-case t)))]
        (recur suite (inc id) (rest rows) (conj tests t))))))

(defn from-yaml
  "Parses tests from a yaml file"
