diff --git a/src/lib.rs b/src/lib.rs
index 0cb90c1..77988bc 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -176,7 +176,7 @@ struct Register;
 
 impl Register {
     const SECONDS   : u8 = 0x00;
- }
+}
 
 const DEVICE_ADDRESS: u8 = 0b110_1000;
 
@@ -262,97 +262,3 @@ where
 }
 
 mod ds323x;
-
-#[cfg(test)]
-mod tests {
-    use super::*;
-    extern crate embedded_hal_mock as hal;
-    extern crate std;
-    use self::std::vec;
-
-    struct DummyOutputPin;
-    impl embedded_hal::digital::OutputPin for DummyOutputPin {
-        fn set_low(&mut self) {}
-        fn set_high(&mut self) {}
-    }
-
-    mod ds3231 {
-        use super::*;
-
-        #[test]
-        fn can_create() {
-            Ds323x::new_ds3231(hal::i2c::Mock::new(&[]));
-        }
-
-        #[test]
-        fn can_get_seconds() {
-            let transactions = [
-                hal::i2c::Transaction::write_read(DEVICE_ADDRESS, vec![Register::SECONDS], vec![1])
-            ];
-            let mut dev = Ds323x::new_ds3231(hal::i2c::Mock::new(&transactions));
-            assert_eq!(1, dev.get_seconds().unwrap());
-        }
-
-        #[test]
-        fn can_set_seconds() {
-            let transactions = [
-                hal::i2c::Transaction::write(DEVICE_ADDRESS, vec![Register::SECONDS, 1])
-            ];
-            let mut dev = Ds323x::new_ds3231(hal::i2c::Mock::new(&transactions));
-            dev.set_seconds(1).unwrap();
-        }
-    }
-    mod ds3232 {
-        use super::*;
-
-        #[test]
-        fn can_create() {
-            Ds323x::new_ds3232(hal::i2c::Mock::new(&[]));
-        }
-
-        #[test]
-        fn can_get_seconds() {
-            let transactions = [
-                hal::i2c::Transaction::write_read(DEVICE_ADDRESS, vec![Register::SECONDS], vec![1])
-            ];
-            let mut dev = Ds323x::new_ds3232(hal::i2c::Mock::new(&transactions));
-            assert_eq!(1, dev.get_seconds().unwrap());
-        }
-
-        #[test]
-        fn can_set_seconds() {
-            let transactions = [
-                hal::i2c::Transaction::write(DEVICE_ADDRESS, vec![Register::SECONDS, 1])
-            ];
-            let mut dev = Ds323x::new_ds3232(hal::i2c::Mock::new(&transactions));
-            dev.set_seconds(1).unwrap();
-        }
-    }
-
-    mod ds3234 {
-        use super::*;
-
-        #[test]
-        fn can_create() {
-            Ds323x::new_ds3234(hal::spi::Mock::new(&[]), DummyOutputPin);
-        }
-
-        #[test]
-        fn can_get_seconds() {
-            let transactions = [
-                hal::spi::Transaction::transfer(vec![Register::SECONDS, 0], vec![Register::SECONDS, 1])
-            ];
-            let mut dev = Ds323x::new_ds3234(hal::spi::Mock::new(&transactions), DummyOutputPin);
-            assert_eq!(1, dev.get_seconds().unwrap());
-        }
-
-        #[test]
-        fn can_set_seconds() {
-            let transactions = [
-                hal::spi::Transaction::write(vec![Register::SECONDS + 0x80, 1])
-            ];
-            let mut dev = Ds323x::new_ds3234(hal::spi::Mock::new(&transactions), DummyOutputPin);
-            dev.set_seconds(1).unwrap();
-        }
-    }
-}
\ No newline at end of file
diff --git a/tests/common/mod.rs b/tests/common/mod.rs
new file mode 100644
index 0000000..44920d8
--- /dev/null
+++ b/tests/common/mod.rs
@@ -0,0 +1,16 @@
+extern crate embedded_hal;
+
+pub const DEVICE_ADDRESS: u8 = 0b110_1000;
+
+pub struct Register;
+
+impl Register {
+    pub const SECONDS   : u8 = 0x00;
+ }
+
+pub struct DummyOutputPin;
+
+impl embedded_hal::digital::OutputPin for DummyOutputPin {
+    fn set_low(&mut self) {}
+    fn set_high(&mut self) {}
+}
diff --git a/tests/ds3231.rs b/tests/ds3231.rs
new file mode 100644
index 0000000..ead07f7
--- /dev/null
+++ b/tests/ds3231.rs
@@ -0,0 +1,11 @@
+extern crate embedded_hal_mock as hal;
+extern crate ds323x;
+use ds323x::Ds323x;
+
+#[test]
+fn can_create_and_destroy() {
+    let dev = Ds323x::new_ds3231(hal::i2c::Mock::new(&[]));
+    let mut i2c = dev.destroy_ds3231();
+    i2c.done();
+}
+    
\ No newline at end of file
diff --git a/tests/ds3232.rs b/tests/ds3232.rs
new file mode 100644
index 0000000..72fdfe0
--- /dev/null
+++ b/tests/ds3232.rs
@@ -0,0 +1,11 @@
+extern crate embedded_hal_mock as hal;
+extern crate ds323x;
+use ds323x::Ds323x;
+
+#[test]
+fn can_create_and_destroy() {
+    let dev = Ds323x::new_ds3232(hal::i2c::Mock::new(&[]));
+    let mut i2c = dev.destroy_ds3232();
+    i2c.done();
+}
+    
\ No newline at end of file
diff --git a/tests/ds3234.rs b/tests/ds3234.rs
new file mode 100644
index 0000000..652c048
--- /dev/null
+++ b/tests/ds3234.rs
@@ -0,0 +1,13 @@
+extern crate embedded_hal_mock as hal;
+extern crate ds323x;
+use ds323x::Ds323x;
+mod common;
+use common::DummyOutputPin;
+
+#[test]
+fn can_create_and_destroy() {
+    let dev = Ds323x::new_ds3234(hal::spi::Mock::new(&[]), DummyOutputPin);
+    let (mut spi, _cs) = dev.destroy_ds3234();
+    spi.done();
+}
+    
\ No newline at end of file
diff --git a/tests/ds323x.rs b/tests/ds323x.rs
new file mode 100644
index 0000000..df26eb0
--- /dev/null
+++ b/tests/ds323x.rs
@@ -0,0 +1,61 @@
+extern crate embedded_hal_mock as hal;
+extern crate ds323x;
+use ds323x::{ Ds323x, interface, ic };
+use hal::i2c::{ Mock as I2cMock, Transaction as I2cTrans };
+use hal::spi::{ Mock as SpiMock, Transaction as SpiTrans };
+mod common;
+use common::{ DEVICE_ADDRESS, Register, DummyOutputPin };
+
+fn new_ds3231(transactions: &[I2cTrans]) -> Ds323x<interface::I2cInterface<I2cMock>, ic::DS3231> {
+    Ds323x::new_ds3231(I2cMock::new(&transactions))
+}
+
+fn new_ds3232(transactions: &[I2cTrans]) -> Ds323x<interface::I2cInterface<I2cMock>, ic::DS3232> {
+    Ds323x::new_ds3232(I2cMock::new(&transactions))
+}
+
+fn new_ds3234(transactions: &[SpiTrans])
+    -> Ds323x<interface::SpiInterface<SpiMock, DummyOutputPin>, ic::DS3234> {
+    Ds323x::new_ds3234(SpiMock::new(&transactions), DummyOutputPin)
+}
+
+macro_rules! get_test {
+    ($name:ident, $method:ident, $create_method:ident, $expected:expr, $transaction:expr) => {
+        #[test]
+        fn $name() {
+            let transactions = [ $transaction ];
+            let mut dev = $create_method(&transactions);
+            assert_eq!($expected, dev.$method().unwrap());
+        }
+    };
+}
+
+macro_rules! set_test {
+    ($name:ident, $method:ident, $create_method:ident, $value:expr, $transaction:expr) => {
+        #[test]
+        fn $name() {
+            let transactions = [ $transaction ];
+            let mut dev = $create_method(&transactions);
+            dev.$method($value).unwrap();
+        }
+    };
+}
+
+get_test!(can_get_seconds_ds3231, get_seconds, new_ds3231, 1,
+          I2cTrans::write_read(DEVICE_ADDRESS, vec![Register::SECONDS], vec![1]));
+
+get_test!(can_get_seconds_ds3232, get_seconds, new_ds3232, 1,
+          I2cTrans::write_read(DEVICE_ADDRESS, vec![Register::SECONDS], vec![1]));
+
+get_test!(can_get_seconds_ds3234, get_seconds, new_ds3234, 1,
+          SpiTrans::transfer(vec![Register::SECONDS, 0], vec![Register::SECONDS, 1]));
+
+
+set_test!(can_set_seconds_ds3231, set_seconds, new_ds3231, 1,
+          I2cTrans::write(DEVICE_ADDRESS, vec![Register::SECONDS, 1]));
+
+set_test!(can_set_seconds_ds3232, set_seconds, new_ds3232, 1,
+          I2cTrans::write(DEVICE_ADDRESS, vec![Register::SECONDS, 1]));
+
+set_test!(can_set_seconds_ds3234, set_seconds, new_ds3234, 1,
+          SpiTrans::write(vec![Register::SECONDS + 0x80, 1]));