diff --git a/.dir-locals.el b/.dir-locals.el
index ef2abb2e2b4a140bbaac66072a6da7237e5f7fff..6ef64b82e46d455fcad94a03c163a4e82d3e35d3 100644
--- a/.dir-locals.el
+++ b/.dir-locals.el
@@ -19,6 +19,7 @@
                               (expect-eval-actual-first 1)
                               (expect-expansion 0)
                               (expect-let 1)
+                              (expect-when-testing-against-dataset 1)
                               (expect-with-all-drivers 1)
                               (ins 1)
                               (let-400 1)
@@ -33,4 +34,5 @@
                               (symbol-macrolet 1)
                               (sync-in-context 2)
                               (upd 2)
+                              (when-testing-dataset 1)
                               (with-credentials 1)))))))
diff --git a/src/metabase/driver.clj b/src/metabase/driver.clj
index c309a516cdd9ddddbc06880027081f6057229e15..fe7ab054d863333d01dbccdeebac7867f29ebca5 100644
--- a/src/metabase/driver.clj
+++ b/src/metabase/driver.clj
@@ -124,12 +124,17 @@
   "Process a structured or native query, and return the result."
   [query]
   {:pre [(map? query)]}
-  (binding [qp/*query* query]
-    (let [driver  (database-id->driver (:database query))
-          query   (qp/preprocess query)
-          results (binding [qp/*query* query]
-                    (i/process-query driver (dissoc-in query [:query :cum_sum])))] ; strip out things that individual impls don't need to know about / deal with
-      (qp/post-process driver query results))))
+  (try
+    (binding [qp/*query* query]
+      (let [driver  (database-id->driver (:database query))
+            query   (qp/preprocess query)
+            results (binding [qp/*query* query]
+                      (i/process-query driver (dissoc-in query [:query :cum_sum])))] ; strip out things that individual impls don't need to know about / deal with
+        (qp/post-process driver query results)))
+    (catch Throwable e
+      (.printStackTrace e)
+      {:status :failed
+       :error  (.getMessage e)})))
 
 
 ;; ## Query Execution Stuff
diff --git a/src/metabase/driver/generic_sql/native.clj b/src/metabase/driver/generic_sql/native.clj
index 38f72290ea09e7f612feca750424d01dbf502e9d..3e5bbf35c692bbdce8294085970566528c613043 100644
--- a/src/metabase/driver/generic_sql/native.clj
+++ b/src/metabase/driver/generic_sql/native.clj
@@ -51,21 +51,14 @@
                                                     (log/debug "Setting timezone to:" timezone)
                                                     (jdbc/db-do-prepared conn set-timezone-sql)))
                                                 (jdbc/query conn sql :as-arrays? true))]
-         {:status :completed
-          :row_count (count rows)
-          :data {:rows rows
-                 :columns columns
-                 :cols (map (fn [column first-value]
-                              {:name column
-                               :base_type (value->base-type first-value)})
-                            columns first-row)}})
+         {:rows rows
+          :columns columns
+          :cols (map (fn [column first-value]
+                       {:name column
+                        :base_type (value->base-type first-value)})
+                     columns first-row)})
        (catch java.sql.SQLException e
-         {:status :failed
-          :error (or (->> (.getMessage e)     ; error message comes back like 'Column "ZID" not found; SQL statement: ... [error-code]' sometimes
-                          (re-find #"^(.*);") ; the user already knows the SQL, and error code is meaningless
-                          second)             ; so just return the part of the exception that is relevant
-                     (.getMessage e))})))
-
-(def db (delay (-> (sel :one Database :id 1)
-                   db->korma-db
-                   korma.db/get-connection)))
+         (throw (Exception. ^String (or (->> (.getMessage e)     ; error message comes back like 'Column "ZID" not found; SQL statement: ... [error-code]' sometimes
+                                             (re-find #"^(.*);") ; the user already knows the SQL, and error code is meaningless
+                                             second)             ; so just return the part of the exception that is relevant
+                                        (.getMessage e)))))))
diff --git a/src/metabase/driver/generic_sql/query_processor.clj b/src/metabase/driver/generic_sql/query_processor.clj
index 81c80c9e364dca2a93ded3289efe659e6ff24645..63566b1ecc16686bf48129acbdec6bde858e4523 100644
--- a/src/metabase/driver/generic_sql/query_processor.clj
+++ b/src/metabase/driver/generic_sql/query_processor.clj
@@ -45,11 +45,10 @@
          eval
          (annotate/annotate query))
     (catch java.sql.SQLException e
-      {:status :failed
-       :error (or (->> (.getMessage e)                       ; error message comes back like "Error message ... [status-code]" sometimes
-                       (re-find  #"(?s)(^.*)\s+\[[\d-]+\]$") ; status code isn't useful and makes unit tests hard to write so strip it off
-                       second)
-                  (.getMessage e))})))                       ; (?s) = Pattern.DOTALL - tell regex `.` to match newline characters as well
+      (throw (Exception. ^String (or (->> (.getMessage e)                       ; error message comes back like "Error message ... [status-code]" sometimes
+                                          (re-find  #"(?s)(^.*)\s+\[[\d-]+\]$") ; status code isn't useful and makes unit tests hard to write so strip it off
+                                          second)                               ; (?s) = Pattern.DOTALL - tell regex `.` to match newline characters as well
+                                     (.getMessage e)))))))
 
 
 (defn process-and-run
diff --git a/src/metabase/driver/query_processor.clj b/src/metabase/driver/query_processor.clj
index 47c37615dd14f5eca4247bbb4ca5eee8be807ccd..71d9de238644dff63e83373681cef0b5cd20ed87 100644
--- a/src/metabase/driver/query_processor.clj
+++ b/src/metabase/driver/query_processor.clj
@@ -188,12 +188,12 @@
 (defn post-process
   "Apply post-processing steps to the RESULTS of a QUERY, such as applying cumulative sum."
   [driver query results]
-  (case (keyword (:type query))
-    :native results
-    :query  (let [query (:query query)]
-              (->> results
-                   (post-process-cumulative-sum query)
-                   add-row-count-and-status))))
+  (->> (case (keyword (:type query))
+         :native results
+         :query  (let [query (:query query)]
+                   (->> results
+                        (post-process-cumulative-sum query))))
+       add-row-count-and-status))
 
 
 ;; # COMMON ANNOTATION FNS
diff --git a/test/metabase/api/meta/db_test.clj b/test/metabase/api/meta/db_test.clj
index 212ecd1bb8ff1964aa3260cbb55f9e9b8f2d7df3..aa6ac209bc076842e58b892c5cc7ef186c5af4fa 100644
--- a/test/metabase/api/meta/db_test.clj
+++ b/test/metabase/api/meta/db_test.clj
@@ -5,6 +5,7 @@
             [metabase.driver.mongo.test-data :as mongo-test-data]
             (metabase.models [database :refer [Database]]
                              [table :refer [Table]])
+            [metabase.test.data.datasets :as datasets]
             [metabase.test-data :refer :all]
             [metabase.test.util :refer [match-$ random-name expect-eval-actual-first]]))
 
@@ -118,36 +119,39 @@
                          :logo_url nil
                          :report_timezone nil
                  :inherits true}]
-        [(match-$ (sel :one Database :name db-name)
-           {:created_at $
-            :engine "postgres"
-            :id $
-            :details {:conn_str "host=localhost port=5432 dbname=fakedb user=cam"}
-            :updated_at $
-            :organization org
-            :name $
-            :organization_id @org-id
-            :description nil})
-         (match-$ @mongo-test-data/mongo-test-db
-           {:created_at $
-            :engine "mongo"
-            :id $
-            :details $
-            :updated_at $
-            :organization org
-            :name "Mongo Test"
-            :organization_id @org-id
-            :description nil})
-         (match-$ @test-db
-           {:created_at $
-            :engine "h2"
-            :id $
-            :details $
-            :updated_at $
-            :organization org
-            :name "Test Database"
-            :organization_id @org-id
-            :description nil})])
+        (filter identity
+                [(datasets/when-testing-dataset :generic-sql
+                   (match-$ (sel :one Database :name db-name)
+                     {:created_at $
+                      :engine "postgres"
+                      :id $
+                      :details {:conn_str "host=localhost port=5432 dbname=fakedb user=cam"}
+                      :updated_at $
+                      :organization org
+                      :name $
+                      :organization_id @org-id
+                      :description nil}))
+                 (datasets/when-testing-dataset :mongo
+                   (match-$ @mongo-test-data/mongo-test-db
+                     {:created_at $
+                      :engine "mongo"
+                      :id $
+                      :details $
+                      :updated_at $
+                      :organization org
+                      :name "Mongo Test"
+                      :organization_id @org-id
+                      :description nil}))
+                 (match-$ @test-db
+                   {:created_at $
+                    :engine "h2"
+                    :id $
+                    :details $
+                    :updated_at $
+                    :organization org
+                    :name "Test Database"
+                    :organization_id @org-id
+                    :description nil})]))
     (do
       ;; Delete all the randomly created Databases we've made so far
       (cascade-delete Database :organization_id @org-id :id [not-in (set [@db-id
diff --git a/test/metabase/api/meta/table_test.clj b/test/metabase/api/meta/table_test.clj
index abce251d3a973be9d0e2943c242270f2e068654a..9367404d75cbebdb39e16ffdf199b36776e207f3 100644
--- a/test/metabase/api/meta/table_test.clj
+++ b/test/metabase/api/meta/table_test.clj
@@ -8,6 +8,7 @@
             (metabase.models [field :refer [Field]]
                              [foreign-key :refer [ForeignKey]]
                              [table :refer [Table]])
+            [metabase.test.data.datasets :as datasets, :refer [*dataset* with-dataset-when-testing]]
             [metabase.test-data :refer :all]
             [metabase.test.util :refer [match-$ expect-eval-actual-first]]))
 
@@ -22,14 +23,14 @@
 
 ;; ## GET /api/meta/table?org
 ;; These should come back in alphabetical order and include relevant metadata
-(expect #{{:name "CATEGORIES", :rows 75,   :active true, :id (table->id :categories),                 :db_id @db-id}
-          {:name "CHECKINS",   :rows 1000, :active true, :id (table->id :checkins),                   :db_id @db-id}
-          {:name "USERS",      :rows 15,   :active true, :id (table->id :users),                      :db_id @db-id}
-          {:name "VENUES",     :rows 100,  :active true, :id (table->id :venues),                     :db_id @db-id}
-          {:name "categories", :rows 75,   :active true, :id (mongo-data/table-name->id :categories), :db_id @mongo-test-db-id}
-          {:name "checkins",   :rows 1000, :active true, :id (mongo-data/table-name->id :checkins),   :db_id @mongo-test-db-id}
-          {:name "users",      :rows 15,   :active true, :id (mongo-data/table-name->id :users),      :db_id @mongo-test-db-id}
-          {:name "venues",     :rows 100,  :active true, :id (mongo-data/table-name->id :venues),     :db_id @mongo-test-db-id}}
+(expect (set (mapcat (fn [dataset-name]
+                       (with-dataset-when-testing dataset-name
+                         (let [db-id (:id (datasets/db *dataset*))]
+                           [{:name (datasets/format-name *dataset* "categories"), :db_id db-id, :active true, :rows   75, :id (datasets/table-name->id *dataset* :categories)}
+                            {:name (datasets/format-name *dataset* "checkins"),   :db_id db-id, :active true, :rows 1000, :id (datasets/table-name->id *dataset* :checkins)}
+                            {:name (datasets/format-name *dataset* "users"),      :db_id db-id, :active true, :rows   15, :id (datasets/table-name->id *dataset* :users)}
+                            {:name (datasets/format-name *dataset* "venues"),     :db_id db-id, :active true, :rows  100, :id (datasets/table-name->id *dataset* :venues)}])))
+                     @datasets/test-dataset-names))
   (->> ((user->client :rasta) :get 200 "meta/table" :org @org-id)
        (map #(dissoc % :db :created_at :updated_at :entity_name :description :entity_type))
        set))
diff --git a/test/metabase/driver/generic_sql/native_test.clj b/test/metabase/driver/generic_sql/native_test.clj
index 87295f434676a826f609cd86c153581b1437f53d..941a9bb00f0a78de87c8172e130924aff60a4c23 100644
--- a/test/metabase/driver/generic_sql/native_test.clj
+++ b/test/metabase/driver/generic_sql/native_test.clj
@@ -1,6 +1,6 @@
 (ns metabase.driver.generic-sql.native-test
   (:require [expectations :refer :all]
-            [metabase.driver.generic-sql.native :refer :all]
+            [metabase.driver :as driver]
             [metabase.test-data :refer :all]))
 
 ;; Just check that a basic query works
@@ -10,8 +10,8 @@
                        [99]]
                 :columns [:id]
                 :cols [{:name :id, :base_type :IntegerField}]}}
-  (process-and-run {:native {:query "SELECT ID FROM VENUES ORDER BY ID DESC LIMIT 2;"}
-                    :database @db-id}))
+  (driver/process-query {:native {:query "SELECT ID FROM VENUES ORDER BY ID DESC LIMIT 2;"}
+                         :database @db-id}))
 
 ;; Check that column ordering is maintained
 (expect
@@ -23,11 +23,11 @@
             :cols [{:name :id, :base_type :IntegerField}
                    {:name :name, :base_type :TextField}
                    {:name :category_id, :base_type :IntegerField}]}}
-  (process-and-run {:native {:query "SELECT ID, NAME, CATEGORY_ID FROM VENUES ORDER BY ID DESC LIMIT 2;"}
-                    :database @db-id}))
+  (driver/process-query {:native {:query "SELECT ID, NAME, CATEGORY_ID FROM VENUES ORDER BY ID DESC LIMIT 2;"}
+                         :database @db-id}))
 
 ;; Check that we get proper error responses for malformed SQL
 (expect {:status :failed
          :error "Column \"ZID\" not found"}
-  (process-and-run {:native {:query "SELECT ZID FROM CHECKINS LIMIT 2;"}
-                    :database @db-id}))
+  (driver/process-query {:native {:query "SELECT ZID FROM CHECKINS LIMIT 2;"}
+                         :database @db-id}))
diff --git a/test/metabase/driver/mongo/test_data.clj b/test/metabase/driver/mongo/test_data.clj
index 9392ccc77daa1d54f5ab44334210417f4ef821eb..2651a081ab9fe2414128dc77820ad082c437d04f 100644
--- a/test/metabase/driver/mongo/test_data.clj
+++ b/test/metabase/driver/mongo/test_data.clj
@@ -39,22 +39,27 @@
   ^{:doc "A delay that fetches or creates the Mongo test `Database`.
           If DB is created, `load-data` and `sync-database!` are called to get the DB in a state that we can use for testing."}
   mongo-test-db
-  (delay (let [db (or (sel :one Database :name mongo-test-db-name)
-                      (let [db (ins Database
-                                 :organization_id @org-id
-                                 :name mongo-test-db-name
-                                 :engine :mongo
-                                 :details {:conn_str mongo-test-db-conn-str})]
-                        (log/info (color/cyan "Loading Mongo test data..."))
-                        (load-data)
-                        (driver/sync-database! db)
-                        (set-field-special-types!)
-                        (log/info (color/cyan "Done."))
-                        db))]
-           (assert (and (map? db)
-                        (integer? (:id db))
-                        (exists? Database :id (:id db))))
-           db)))
+  (delay
+   ;; Resolve metabase.test.data.datasets at runtime to avoid circular dependency
+   (require 'metabase.test.data.datasets)
+   (assert (contains? @@(ns-resolve 'metabase.test.data.datasets 'test-dataset-names) :mongo)
+           "Why are we attempting to use the Mongo test Database when we're not testing against mongo?")
+   (let [db (or (sel :one Database :name mongo-test-db-name)
+                (let [db (ins Database
+                           :organization_id @org-id
+                           :name mongo-test-db-name
+                           :engine :mongo
+                           :details {:conn_str mongo-test-db-conn-str})]
+                  (log/info (color/cyan "Loading Mongo test data..."))
+                  (load-data)
+                  (driver/sync-database! db)
+                  (set-field-special-types!)
+                  (log/info (color/cyan "Done."))
+                  db))]
+     (assert (and (map? db)
+                  (integer? (:id db))
+                  (exists? Database :id (:id db))))
+     db)))
 
 (defonce
   ^{:doc "A Delay that returns the ID of `mongo-test-db`, forcing creation of it if needed."}
diff --git a/test/metabase/driver/mongo_test.clj b/test/metabase/driver/mongo_test.clj
index bb94e19e935da54408284a0d9e5964297ad07e3d..2538795bb407aadda7b2b44277511e360c8fcf1d 100644
--- a/test/metabase/driver/mongo_test.clj
+++ b/test/metabase/driver/mongo_test.clj
@@ -10,8 +10,16 @@
             (metabase.models [field :refer [Field]]
                              [table :refer [Table]])
             [metabase.test-data.data :refer [test-data]]
+            [metabase.test.data.datasets :as datasets]
             [metabase.test.util :refer [expect-eval-actual-first resolve-private-fns]]))
 
+;; ## Logic for selectively running mongo
+
+(defmacro expect-when-testing-mongo [expected actual]
+  `(datasets/expect-when-testing-dataset :mongo
+     ~expected
+     ~actual))
+
 ;; ## Constants + Helper Fns/Macros
 ;; TODO - move these to metabase.test-data ?
 (def ^:private ^:const table-names
@@ -56,35 +64,35 @@
 
 ;; ## Tests for connection functions
 
-(expect true
+(expect-when-testing-mongo true
   (driver/can-connect? @mongo-test-db))
 
-(expect false
+(expect-when-testing-mongo false
   (driver/can-connect? {:engine :mongo
                         :details {:conn_str "mongodb://123.4.5.6/bad-db-name?connectTimeoutMS=50"}})) ; timeout after 50ms instead of 10s so test's don't take forever
 
-(expect false
+(expect-when-testing-mongo false
   (driver/can-connect? {:engine :mongo
                         :details {:conn_str "mongodb://localhost:3000/bad-db-name?connectTimeoutMS=50"}}))
 
-(expect false
+(expect-when-testing-mongo false
   (driver/can-connect-with-details? :mongo {}))
 
-(expect true
+(expect-when-testing-mongo true
   (driver/can-connect-with-details? :mongo {:host "localhost"
                                             :port 27017
                                             :dbname "metabase-test"}))
 
 ;; should use default port 27017 if not specified
-(expect true
+(expect-when-testing-mongo true
   (driver/can-connect-with-details? :mongo {:host "localhost"
                                             :dbname "metabase-test"}))
 
-(expect false
+(expect-when-testing-mongo false
   (driver/can-connect-with-details? :mongo {:host "123.4.5.6"
                                             :dbname "bad-db-name?connectTimeoutMS=50"}))
 
-(expect false
+(expect-when-testing-mongo false
   (driver/can-connect-with-details? :mongo {:host "localhost"
                                             :port 3000
                                             :dbname "bad-db-name?connectTimeoutMS=50"}))
@@ -95,12 +103,12 @@
 (resolve-private-fns metabase.driver.mongo field->base-type table->column-names)
 
 ;; ### active-table-names
-(expect
+(expect-when-testing-mongo
     #{"checkins" "categories" "users" "venues"}
   (i/active-table-names mongo/driver @mongo-test-db))
 
 ;; ### table->column-names
-(expect
+(expect-when-testing-mongo
     [#{:_id :name}
      #{:_id :date :venue_id :user_id}
      #{:_id :name :last_login}
@@ -110,7 +118,7 @@
        (map table->column-names)))
 
 ;; ### field->base-type
-(expect
+(expect-when-testing-mongo
     [:IntegerField  ; categories._id
      :TextField     ; categories.name
      :IntegerField  ; checkins._id
@@ -131,7 +139,7 @@
        (mapv field->base-type)))
 
 ;; ### active-column-names->type
-(expect
+(expect-when-testing-mongo
     [{"_id" :IntegerField, "name" :TextField}
      {"_id" :IntegerField, "date" :DateField, "venue_id" :IntegerField, "user_id" :IntegerField}
      {"_id" :IntegerField, "name" :TextField, "last_login" :DateField}
@@ -141,7 +149,7 @@
        (mapv (partial i/active-column-names->type mongo/driver))))
 
 ;; ### table-pks
-(expect
+(expect-when-testing-mongo
     [#{"_id"} #{"_id"} #{"_id"} #{"_id"}] ; _id for every table
   (->> table-names
        (map table-name->fake-table)
@@ -151,7 +159,7 @@
 ;; ## Big-picture tests for the way data should look post-sync
 
 ;; Test that Tables got synced correctly, and row counts are correct
-(expect
+(expect-when-testing-mongo
     [{:rows 75, :active true, :name "categories"}
      {:rows 1000, :active true, :name "checkins"}
      {:rows 15, :active true, :name "users"}
@@ -159,7 +167,7 @@
   (sel :many :fields [Table :name :active :rows] :db_id @mongo-test-db-id (k/order :name)))
 
 ;; Test that Fields got synced correctly, and types are correct
-(expect
+(expect-when-testing-mongo
     [[{:special_type :id, :base_type :IntegerField, :name "_id"}
       {:special_type :category, :base_type :DateField, :name "last_login"}
       {:special_type :category, :base_type :TextField, :name "name"}]
diff --git a/test/metabase/driver/query_processor_test.clj b/test/metabase/driver/query_processor_test.clj
index 104b3f2a6ec3561a92bee04ec46d97ae8d0354a0..dc601c4528338820d5664601af037463007821bb 100644
--- a/test/metabase/driver/query_processor_test.clj
+++ b/test/metabase/driver/query_processor_test.clj
@@ -4,67 +4,37 @@
             [metabase.db :refer :all]
             [metabase.driver :as driver]
             (metabase.models [table :refer [Table]])
-            [metabase.test.data.datasets :as datasets]))
-
-;; ## Functionality for writing driver-independent tests
-
-(def ^:dynamic *db*
-  "Bound to `Database` for the current driver inside body of `with-dataset`.")
-(def ^:dynamic *db-id*
-  "Bound to ID of `Database` for the current driver inside body of `with-dataset`.")
-(def ^:dynamic *driver-dataset*)
-
-
-;; ###  EXPECT-WITH-ALL-DRIVERS
-
-(defmacro with-dataset
-  "Execute BODY with `*driver-dataset*`, `*db*` and `*db-id*` bound to appropriate values for DRIVER-NAME."
-  [dataset-name & body]
-  {:pre [(keyword? dataset-name)
-         (contains? datasets/all-valid-dataset-names dataset-name)]}
-  `(let [dataset# (datasets/dataset-name->dataset ~dataset-name)
-         db#      (datasets/db dataset#)]
-     (binding [*driver-dataset* dataset#
-               *db*             db#
-               *db-id*          (:id db#)]
-       (assert (and (integer? *db-id*)
-                    (map? *db*)))
-       ~@body)))
-
-(defmacro expect-with-all-datasets
-  "Like expect, but runs a test inside of `with-dataset` for *each* of the available datasets."
-  [expected actual]
-  `(do ~@(mapcat (fn [dataset-name]
-                   `[(expect
-                         (with-dataset ~dataset-name
-                           ~expected)
-                       (with-dataset ~dataset-name
-                         ~actual))])
-                 @datasets/test-dataset-names)))
-
+            [metabase.test.data.datasets :as datasets :refer [*dataset* expect-with-all-datasets]]))
 
 ;; ##  Dataset-Independent Data Fns
 
-(defn ->table
-  "Given keyword TABLE-NAME, fetch corresponding `Table` in `*db*`."
-  [table-name]
-  {:pre [*driver-dataset*]
-   :post [(map? %)]}
-  (datasets/table-name->table *driver-dataset* table-name))
-
 (defn id
   "Return the ID of a `Table` or `Field` for the current driver data set."
   ([table-name]
-   {:pre [*driver-dataset*
+   {:pre [*dataset*
           (keyword? table-name)]
     :post [(integer? %)]}
-   (:id (->table table-name)))
+   (datasets/table-name->id *dataset* table-name))
   ([table-name field-name]
-   {:pre [*driver-dataset*
+   {:pre [*dataset*
           (keyword? table-name)
           (keyword? field-name)]
     :post [(integer? %)]}
-   (datasets/field-name->id *driver-dataset* table-name field-name)))
+   (datasets/field-name->id *dataset* table-name field-name)))
+
+(defn db-id []
+  {:pre  [*dataset*]
+   :post [(integer? %)]}
+  (:id (datasets/db *dataset*)))
+
+(defn fks-supported? []
+  (datasets/fks-supported? *dataset*))
+
+(defn format-name [name]
+  (datasets/format-name *dataset* name))
+
+(defn id-field-type []
+  (datasets/id-field-type *dataset*))
 
 
 ;; ## Dataset-Independent QP Tests
@@ -79,18 +49,9 @@
         :row_count ~(count (:rows data))
         :data ~data}
      (driver/process-query {:type :query
-                            :database *db-id*
+                            :database (db-id)
                             :query ~query})))
 
-(defn fks-supported? []
-  (datasets/fks-supported? *driver-dataset*))
-
-(defn format-name [name]
-  (datasets/format-name *driver-dataset* name))
-
-(defn id-field-type []
-  (datasets/id-field-type *driver-dataset*))
-
 (defn ->columns
   "Generate the vector that should go in the `columns` part of a QP result; done by calling `format-name` against each column name."
   [& names]
@@ -547,7 +508,7 @@
      :row_count 0
      :data {:rows [], :columns [], :cols []}}
   (driver/process-query {:type :query
-                         :database *db-id*
+                         :database (db-id)
                          :native {}
                          :query {:source_table 0
                                  :filter [nil nil]
diff --git a/test/metabase/test/data/datasets.clj b/test/metabase/test/data/datasets.clj
index 84e54a349a2d18769ede05eeecca770addf8e8ae..9a3f89503913c175c0109b1a4ffa8f54475139a5 100644
--- a/test/metabase/test/data/datasets.clj
+++ b/test/metabase/test/data/datasets.clj
@@ -4,6 +4,7 @@
             [clojure.tools.logging :as log]
             [colorize.core :as color]
             [environ.core :refer [env]]
+            [expectations :refer :all]
             [metabase.driver.mongo.test-data :as mongo-data]
             [metabase.test-data :as generic-sql-data]))
 
@@ -17,6 +18,8 @@
     "Return `Database` containing test data for this driver.")
   (table-name->table [this table-name]
     "Given a TABLE-NAME keyword like `:venues`, *fetch* the corresponding `Table`.")
+  (table-name->id [this table-name]
+    "Given a TABLE-NAME keyword like `:venues`, return corresponding `Table` ID.")
   (field-name->id [this table-name field-name]
     "Given keyword TABLE-NAME and FIELD-NAME, return the corresponding `Field` ID.")
   (fks-supported? [this]
@@ -38,11 +41,12 @@
     (mongo-data/destroy!)
     @mongo-data/mongo-test-db
     (assert (integer? @mongo-data/mongo-test-db-id)))
-
   (db [_]
     @mongo-data/mongo-test-db)
   (table-name->table [_ table-name]
     (mongo-data/table-name->table table-name))
+  (table-name->id [_ table-name]
+    (mongo-data/table-name->id table-name))
   (field-name->id [_ table-name field-name]
     (mongo-data/field-name->id table-name (if (= field-name :id) :_id
                                               field-name)))
@@ -51,7 +55,6 @@
   (format-name [_ table-or-field-name]
     (if (= table-or-field-name "id") "_id"
         table-or-field-name))
-
   (id-field-type [_]
     :IntegerField))
 
@@ -63,19 +66,18 @@
   (load-data! [_]
     @generic-sql-data/test-db
     (assert (integer? @generic-sql-data/db-id)))
-
   (db [_]
     @generic-sql-data/test-db)
   (table-name->table [_ table-name]
     (generic-sql-data/table-name->table table-name))
+  (table-name->id [_ table-name]
+    (generic-sql-data/table->id table-name))
   (field-name->id [_ table-name field-name]
     (generic-sql-data/field->id table-name field-name))
-
   (fks-supported? [_]
     true)
   (format-name [_ table-or-field-name]
     (clojure.string/upper-case table-or-field-name))
-
   (id-field-type [_]
     :BigIntegerField))
 
@@ -124,3 +126,61 @@
                             all-valid-dataset-names)]
            (log/info (color/green "Running QP tests against these datasets: " datasets))
            datasets)))
+
+
+;; # Helper Macros
+
+(def ^:dynamic *dataset*
+  "The dataset we're currently testing against, bound by `with-dataset`."
+  nil)
+
+(defmacro with-dataset
+  "Bind `*dataset*` to the dataset with DATASET-NAME and execute BODY."
+  [dataset-name & body]
+  `(binding [*dataset* (dataset-name->dataset ~dataset-name)]
+     ~@body))
+
+(defmacro when-testing-dataset
+  "Execute BODY only if we're currently testing against DATASET-NAME."
+  [dataset-name & body]
+  `(when (contains? @test-dataset-names ~dataset-name)
+     ~@body))
+
+(defmacro with-dataset-when-testing
+  "When testing DATASET-NAME, binding `*dataset*` and executes BODY."
+  [dataset-name & body]
+  `(when-testing-dataset ~dataset-name
+     (with-dataset ~dataset-name
+       ~@body)))
+
+(defmacro expect-when-testing-dataset
+  "Generate a unit test that only runs if we're currently testing against DATASET-NAME."
+  [dataset-name expected actual]
+  `(expect
+       (when-testing-dataset ~dataset-name
+         ~expected)
+     (when-testing-dataset ~dataset-name
+       ~actual)))
+
+(defmacro expect-with-dataset
+  "Generate a unit test that only runs if we're currently testing against DATASET-NAME, and that binds `*dataset*` to the current dataset."
+  [dataset-name expected actual]
+  `(expect-when-testing-dataset ~dataset-name
+     (with-dataset ~dataset-name
+       ~expected)
+     (with-dataset ~dataset-name
+       ~actual)))
+
+(defmacro expect-with-datasets
+  "Generate unit tests for all datasets in DATASET-NAMES; each test will only run if we're currently testing the corresponding dataset.
+   `*dataset*` is bound to the current dataset inside each test."
+  [dataset-names expected actual]
+  `(do ~@(map (fn [dataset-name]
+                `(expect-with-dataset ~dataset-name ~expected ~actual))
+              dataset-names)))
+
+(defmacro expect-with-all-datasets
+  "Generate unit tests for all valid datasets; each test will only run if we're currently testing the corresponding dataset.
+  `*dataset*` is bound to the current dataset inside each test."
+  [expected actual]
+  `(expect-with-datasets ~all-valid-dataset-names ~expected ~actual))