diff --git a/maud_macros/tests/basic_syntax.rs b/maud_macros/tests/basic_syntax.rs
new file mode 100644
index 0000000..949b5d4
--- /dev/null
+++ b/maud_macros/tests/basic_syntax.rs
@@ -0,0 +1,145 @@
+#![feature(plugin)]
+#![plugin(maud_macros)]
+
+extern crate maud;
+
+#[test]
+fn literals() {
+    let mut s = String::new();
+    html!(s, "du\tcks" -23 3.14 '\n' "geese").unwrap();
+    assert_eq!(s, "du\tcks-233.14\ngeese");
+}
+
+#[test]
+fn escaping() {
+    let mut s = String::new();
+    html!(s, "<flim&flam>").unwrap();
+    assert_eq!(s, "&lt;flim&amp;flam&gt;");
+}
+
+#[test]
+fn semicolons() {
+    let mut s = String::new();
+    html!(s, {
+        "one";
+        "two";
+        "three";
+        ;;;;;;;;;;;;;;;;;;;;;;;;
+        "four";
+    }).unwrap();
+    assert_eq!(s, "onetwothreefour");
+}
+
+#[test]
+fn blocks() {
+    let mut s = String::new();
+    html!(s, {
+        "hello"
+        {
+            " ducks" " geese"
+        }
+        " swans"
+    }).unwrap();
+    assert_eq!(s, "hello ducks geese swans");
+}
+
+#[test]
+fn simple_elements() {
+    let mut s = String::new();
+    html!(s, p { b { "pickle" } "barrel" i { "kumquat" } }).unwrap();
+    assert_eq!(s, "<p><b>pickle</b>barrel<i>kumquat</i></p>");
+}
+
+#[test]
+fn nesting_elements() {
+    let mut s = String::new();
+    html!(s, html body div p sup "butts").unwrap();
+    assert_eq!(s, "<html><body><div><p><sup>butts</sup></p></div></body></html>");
+}
+
+#[test]
+fn empty_elements() {
+    let mut s = String::new();
+    html!(s, "pinkie" br/ "pie").unwrap();
+    assert_eq!(s, "pinkie<br>pie");
+}
+
+#[test]
+fn simple_attributes() {
+    let mut s = String::new();
+    html!(s, {
+        link rel="stylesheet" href="styles.css"/
+        section id="midriff" {
+            p class="hotpink" "Hello!"
+        }
+    }).unwrap();
+    assert_eq!(s, concat!(
+            r#"<link rel="stylesheet" href="styles.css">"#,
+            r#"<section id="midriff"><p class="hotpink">Hello!</p></section>"#));
+}
+
+#[test]
+fn empty_attributes() {
+    let mut s = String::new();
+    html!(s, div readonly? input type="checkbox" checked? /).unwrap();
+    assert_eq!(s, r#"<div readonly><input type="checkbox" checked></div>"#);
+}
+
+#[test]
+fn colons_in_names() {
+    let mut s = String::new();
+    html!(s, pon-pon:controls-alpha a on:click="yay()" "Yay!").unwrap();
+    assert_eq!(s, concat!(
+            r#"<pon-pon:controls-alpha>"#,
+            r#"<a on:click="yay()">Yay!</a>"#,
+            r#"</pon-pon:controls-alpha>"#));
+}
+
+#[test]
+fn hyphens_in_element_names() {
+    let mut s = String::new();
+    html!(s, custom-element {}).unwrap();
+    assert_eq!(s, "<custom-element></custom-element>");
+}
+
+#[test]
+fn hyphens_in_attribute_names() {
+    let mut s = String::new();
+    html!(s, this sentence-is="false" of-course? {}).unwrap();
+    assert_eq!(s, r#"<this sentence-is="false" of-course></this>"#);
+}
+
+#[test]
+fn class_shorthand() {
+    let mut s = String::new();
+    html!(s, p { "Hi, " span.name { "Lyra" } "!" }).unwrap();
+    assert_eq!(s, r#"<p>Hi, <span class="name">Lyra</span>!</p>"#);
+}
+
+#[test]
+fn class_shorthand_with_space() {
+    let mut s = String::new();
+    html!(s, p { "Hi, " span .name { "Lyra" } "!" }).unwrap();
+    assert_eq!(s, r#"<p>Hi, <span class="name">Lyra</span>!</p>"#);
+}
+
+#[test]
+fn classes_shorthand() {
+    let mut s = String::new();
+    html!(s, p { "Hi, " span.name.here { "Lyra" } "!" }).unwrap();
+    assert_eq!(s, r#"<p>Hi, <span class="name here">Lyra</span>!</p>"#);
+}
+
+#[test]
+fn ids_shorthand() {
+    let mut s = String::new();
+    html!(s, p { "Hi, " span#thing { "Lyra" } "!" }).unwrap();
+    assert_eq!(s, r#"<p>Hi, <span id="thing">Lyra</span>!</p>"#);
+}
+
+#[test]
+fn classes_attrs_ids_mixed_up() {
+    let mut s = String::new();
+    html!(s, p { "Hi, " span.name.here lang="en" #thing { "Lyra" } "!" }).unwrap();
+    assert_eq!(s, "<p>Hi, <span lang=\"en\" class=\"name here\" id=\"thing\">Lyra</span>!</p>");
+}
diff --git a/maud_macros/tests/control_structures.rs b/maud_macros/tests/control_structures.rs
new file mode 100644
index 0000000..fdfdb76
--- /dev/null
+++ b/maud_macros/tests/control_structures.rs
@@ -0,0 +1,139 @@
+#![feature(plugin)]
+#![plugin(maud_macros)]
+
+extern crate maud;
+
+use std::fmt;
+
+#[test]
+fn if_expr() {
+    for (number, &name) in (1..4).zip(["one", "two", "three"].iter()) {
+        let mut s = String::new();
+        html!(s, {
+            @if number == 1 {
+                "one"
+            } @else if number == 2 {
+                "two"
+            } @else if number == 3 {
+                "three"
+            } @else {
+                "oh noes"
+            }
+        }).unwrap();
+        assert_eq!(s, name);
+    }
+}
+
+#[test]
+fn if_let() {
+    for &(input, output) in [(Some("yay"), "yay"), (None, "oh noes")].iter() {
+        let mut s = String::new();
+        html!(s, {
+            @if let Some(value) = input {
+                ^value
+            } @else {
+                "oh noes"
+            }
+        }).unwrap();
+        assert_eq!(s, output);
+    }
+}
+
+#[test]
+fn for_expr() {
+    let ponies = ["Apple Bloom", "Scootaloo", "Sweetie Belle"];
+    let mut s = String::new();
+    html!(s, {
+        ul @for pony in &ponies {
+            li ^pony
+        }
+    }).unwrap();
+    assert_eq!(s, concat!(
+            "<ul>",
+            "<li>Apple Bloom</li>",
+            "<li>Scootaloo</li>",
+            "<li>Sweetie Belle</li>",
+            "</ul>"));
+}
+
+#[test]
+fn match_expr() {
+    for &(input, output) in [(Some("yay"), "<div>yay</div>"), (None, "oh noes")].iter() {
+        let mut s = String::new();
+        html!(s, {
+            @match input {
+                Some(value) => {
+                    div { ^value }
+                },
+                None => {
+                    "oh noes"
+                },
+            }
+        }).unwrap();
+        assert_eq!(s, output);
+    }
+}
+
+#[test]
+fn match_expr_without_delims() {
+    for &(input, output) in [(Some("yay"), "yay"), (None, "<span>oh noes</span>")].iter() {
+        let mut s = String::new();
+        html!(s, {
+            @match input {
+                Some(value) => ^value,
+                None => span { "oh noes" },
+            }
+        }).unwrap();
+        assert_eq!(s, output);
+    }
+}
+
+#[test]
+fn match_expr_with_guards() {
+    for &(input, output) in [(Some(1), "one"), (None, "none"), (Some(2), "2")].iter() {
+        let mut s = String::new();
+        html!(s, {
+            @match input {
+                Some(value) if value == 1 => "one",
+                Some(value) => ^value,
+                None => "none",
+            }
+        }).unwrap();
+        assert_eq!(s, output);
+    }
+}
+
+#[test]
+fn match_in_attribute() {
+    for &(input, output) in [(1, "<span class=\"one\">1</span>"), (2, "<span class=\"two\">2</span>"), (3, "<span class=\"many\">3</span>")].iter() {
+        let mut s = String::new();
+        html!(s, {
+            span class=@match input {
+                1 => "one",
+                2 => "two",
+                _ => "many",
+            } { ^input }
+        }).unwrap();
+        assert_eq!(s, output);
+    }
+}
+
+#[test]
+fn call() {
+    fn ducks(w: &mut fmt::Write) -> fmt::Result {
+        write!(w, "Ducks")
+    }
+    let mut s = String::new();
+    let swans = |yes|
+        if yes {
+            |w: &mut fmt::Write| write!(w, "Swans")
+        } else {
+            panic!("oh noes")
+        };
+    html!(s, {
+        @call ducks
+        @call (|w: &mut fmt::Write| write!(w, "Geese"))
+        @call swans(true)
+    }).unwrap();
+    assert_eq!(s, "DucksGeeseSwans");
+}
diff --git a/maud_macros/tests/misc.rs b/maud_macros/tests/misc.rs
new file mode 100644
index 0000000..7d68553
--- /dev/null
+++ b/maud_macros/tests/misc.rs
@@ -0,0 +1,142 @@
+#![feature(plugin)]
+#![plugin(maud_macros)]
+
+extern crate maud;
+
+use std::fmt;
+
+#[test]
+fn html_utf8() {
+    let mut buf = vec![];
+    html_utf8!(buf, p "hello").unwrap();
+    assert_eq!(buf, b"<p>hello</p>");
+}
+
+#[test]
+fn issue_13() {
+    let owned = String::from("yay");
+    let mut s = String::new();
+    html!(s, ^owned).unwrap();
+    // Make sure the `html!` call didn't move it
+    let _owned = owned;
+}
+
+#[test]
+fn issue_21() {
+    macro_rules! greet {
+        () => ({
+            let mut result = String::new();
+            let name = "Pinkie Pie";
+            html!(result, p { "Hello, " ^name "!" }).map(|()| result)
+        })
+    }
+
+    let s = greet!().unwrap();
+    assert_eq!(s, "<p>Hello, Pinkie Pie!</p>");
+}
+
+#[test]
+fn issue_21_2() {
+    macro_rules! greet {
+        ($name:expr) => ({
+            let mut result = String::new();
+            html!(result, p { "Hello, " ^$name "!" }).map(|()| result)
+        })
+    }
+
+    let s = greet!("Pinkie Pie").unwrap();
+    assert_eq!(s, "<p>Hello, Pinkie Pie!</p>");
+}
+
+#[test]
+fn issue_23() {
+    macro_rules! to_string {
+        ($($x:tt)*) => {{
+            let mut s = String::new();
+            html!(s, $($x)*).unwrap();
+            s
+        }}
+    }
+
+    let name = "Lyra";
+    let s = to_string!(p { "Hi, " ^name "!" });
+    assert_eq!(s, "<p>Hi, Lyra!</p>");
+}
+
+#[test]
+fn issue_26() {
+    macro_rules! to_string {
+        ($($x:tt)*) => {{
+            let mut s = String::new();
+            html!(s, $($x)*).unwrap();
+            s
+        }}
+    }
+
+    let name = "Lyra";
+    let s = to_string!(p { "Hi, " ^(name) "!" });
+    assert_eq!(s, "<p>Hi, Lyra!</p>");
+}
+
+#[test]
+fn issue_26_2() {
+    macro_rules! to_string {
+        ($($x:tt)*) => {{
+            let mut s = String::new();
+            html!(s, $($x)*).unwrap();
+            s
+        }}
+    }
+
+    let name = "Lyra";
+    let s = to_string!(p { "Hi, " ^("person called ".to_string() + name) "!" });
+    assert_eq!(s, "<p>Hi, person called Lyra!</p>");
+}
+
+#[test]
+fn issue_26_3() {
+    macro_rules! to_string {
+        ($($x:tt)*) => {{
+            let mut s = String::new();
+            html!(s, $($x)*).unwrap();
+            s
+        }}
+    }
+
+    let name = "Lyra";
+    let s = to_string!(p { "Hi, " ^{"person called ".to_string() + name} "!" });
+    assert_eq!(s, "<p>Hi, person called Lyra!</p>");
+}
+
+#[test]
+fn render_impl() {
+    struct R(&'static str);
+    impl maud::Render for R {
+        fn render(&self, w: &mut fmt::Write) -> fmt::Result {
+            w.write_str(self.0)
+        }
+    }
+
+    let mut s = String::new();
+    let r = R("pinkie");
+    // Since `R` is not `Copy`, this shows that Maud will auto-ref splice
+    // arguments to find a `Render` impl
+    html!(s, ^r).unwrap();
+    html!(s, ^r).unwrap();
+    assert_eq!(s, "pinkiepinkie");
+}
+
+#[test]
+fn render_once_impl() {
+    struct Once(String);
+    impl maud::RenderOnce for Once {
+        fn render_once(self, w: &mut fmt::Write) -> fmt::Result {
+            w.write_str(&self.0)
+        }
+    }
+
+    let mut s = String::new();
+    let once = Once(String::from("pinkie"));
+    html!(s, ^once).unwrap();
+    assert_eq!(s, "pinkie");
+}
diff --git a/maud_macros/tests/splices.rs b/maud_macros/tests/splices.rs
new file mode 100644
index 0000000..e57972f
--- /dev/null
+++ b/maud_macros/tests/splices.rs
@@ -0,0 +1,124 @@
+#![feature(plugin)]
+#![plugin(maud_macros)]
+
+extern crate maud;
+
+#[test]
+fn literals() {
+    let mut s = String::new();
+    html!(s, ^"<pinkie>").unwrap();
+    assert_eq!(s, "&lt;pinkie&gt;");
+}
+
+#[test]
+fn raw_literals() {
+    use maud::PreEscaped;
+    let mut s = String::new();
+    html!(s, ^PreEscaped("<pinkie>")).unwrap();
+    assert_eq!(s, "<pinkie>");
+}
+
+#[test]
+fn blocks() {
+    let mut s = String::new();
+    html!(s, {
+        ^{
+            let mut result = 1i32;
+            for i in 2..11 {
+                result *= i;
+            }
+            result
+        }
+    }).unwrap();
+    assert_eq!(s, "3628800");
+}
+
+#[test]
+fn attributes() {
+    let rocks = true;
+    let mut s = String::new();
+    html!(s, {
+        input checked?=true /
+        input checked?=false /
+        input checked?=rocks /
+        input checked?=(!rocks) /
+    }).unwrap();
+    assert_eq!(s, concat!(
+            r#"<input checked>"#,
+            r#"<input>"#,
+            r#"<input checked>"#,
+            r#"<input>"#));
+}
+
+static BEST_PONY: &'static str = "Pinkie Pie";
+
+#[test]
+fn statics() {
+    let mut s = String::new();
+    html!(s, ^BEST_PONY).unwrap();
+    assert_eq!(s, "Pinkie Pie");
+}
+
+#[test]
+fn locals() {
+    let best_pony = "Pinkie Pie";
+    let mut s = String::new();
+    html!(s, ^best_pony).unwrap();
+    assert_eq!(s, "Pinkie Pie");
+}
+
+/// An example struct, for testing purposes only
+struct Creature {
+    name: &'static str,
+    /// Rating out of 10, where:
+    /// * 0 is a naked mole rat with dysentery
+    /// * 10 is Sweetie Belle in a milkshake
+    adorableness: u32,
+}
+
+impl Creature {
+    fn repugnance(&self) -> u32 {
+        10 - self.adorableness
+    }
+}
+
+#[test]
+fn structs() {
+    let pinkie = Creature {
+        name: "Pinkie Pie",
+        adorableness: 9,
+    };
+    let mut s = String::new();
+    html!(s, {
+        "Name: " ^pinkie.name ". Rating: " ^pinkie.repugnance()
+    }).unwrap();
+    assert_eq!(s, "Name: Pinkie Pie. Rating: 1");
+}
+
+#[test]
+fn tuple_accessors() {
+    let mut s = String::new();
+    let a = ("ducks", "geese");
+    html!(s, ^a.0).unwrap();
+    assert_eq!(s, "ducks");
+}
+
+#[test]
+fn splice_with_path() {
+    mod inner {
+        pub fn name() -> &'static str {
+            "Maud"
+        }
+    }
+    let mut s = String::new();
+    html!(s, ^inner::name()).unwrap();
+    assert_eq!(s, "Maud");
+}
+
+#[test]
+fn nested_macro_invocation() {
+    let best_pony = "Pinkie Pie";
+    let mut s = String::new();
+    html!(s, ^(format!("{}", best_pony))).unwrap();
+    assert_eq!(s, "Pinkie Pie");
+}
diff --git a/maud_macros/tests/tests.rs b/maud_macros/tests/tests.rs
deleted file mode 100644
index 71cace1..0000000
--- a/maud_macros/tests/tests.rs
+++ /dev/null
@@ -1,564 +0,0 @@
-#![feature(plugin)]
-#![plugin(maud_macros)]
-
-extern crate maud;
-
-use std::fmt;
-
-#[test]
-fn literals() {
-    let mut s = String::new();
-    html!(s, "du\tcks" -23 3.14 '\n' "geese").unwrap();
-    assert_eq!(s, "du\tcks-233.14\ngeese");
-}
-
-#[test]
-fn escaping() {
-    let mut s = String::new();
-    html!(s, "<flim&flam>").unwrap();
-    assert_eq!(s, "&lt;flim&amp;flam&gt;");
-}
-
-#[test]
-fn semicolons() {
-    let mut s = String::new();
-    html!(s, {
-        "one";
-        "two";
-        "three";
-        ;;;;;;;;;;;;;;;;;;;;;;;;
-        "four";
-    }).unwrap();
-    assert_eq!(s, "onetwothreefour");
-}
-
-#[test]
-fn blocks() {
-    let mut s = String::new();
-    html!(s, {
-        "hello"
-        {
-            " ducks" " geese"
-        }
-        " swans"
-    }).unwrap();
-    assert_eq!(s, "hello ducks geese swans");
-}
-
-mod elements {
-    #[test]
-    fn simple() {
-        let mut s = String::new();
-        html!(s, p { b { "pickle" } "barrel" i { "kumquat" } }).unwrap();
-        assert_eq!(s, "<p><b>pickle</b>barrel<i>kumquat</i></p>");
-    }
-
-    #[test]
-    fn nesting() {
-        let mut s = String::new();
-        html!(s, html body div p sup "butts").unwrap();
-        assert_eq!(s, "<html><body><div><p><sup>butts</sup></p></div></body></html>");
-    }
-
-    #[test]
-    fn empty() {
-        let mut s = String::new();
-        html!(s, "pinkie" br/ "pie").unwrap();
-        assert_eq!(s, "pinkie<br>pie");
-    }
-
-    #[test]
-    fn attributes() {
-        let mut s = String::new();
-        html!(s, {
-            link rel="stylesheet" href="styles.css"/
-            section id="midriff" {
-                p class="hotpink" "Hello!"
-            }
-        }).unwrap();
-        assert_eq!(s, concat!(
-                r#"<link rel="stylesheet" href="styles.css">"#,
-                r#"<section id="midriff"><p class="hotpink">Hello!</p></section>"#));
-    }
-
-    #[test]
-    fn empty_attributes() {
-        let mut s = String::new();
-        html!(s, div readonly? input type="checkbox" checked? /).unwrap();
-        assert_eq!(s, r#"<div readonly><input type="checkbox" checked></div>"#);
-    }
-
-    #[test]
-    fn namespaces() {
-        let mut s = String::new();
-        html!(s, pon-pon:controls-alpha a on:click="yay()" "Yay!").unwrap();
-        assert_eq!(s, r#"<pon-pon:controls-alpha><a on:click="yay()">Yay!</a></pon-pon:controls-alpha>"#);
-    }
-}
-
-mod splices {
-    #[test]
-    fn literals() {
-        let mut s = String::new();
-        html!(s, ^"<pinkie>").unwrap();
-        assert_eq!(s, "&lt;pinkie&gt;");
-    }
-
-    #[test]
-    fn raw_literals() {
-        use maud::PreEscaped;
-        let mut s = String::new();
-        html!(s, ^PreEscaped("<pinkie>")).unwrap();
-        assert_eq!(s, "<pinkie>");
-    }
-
-    #[test]
-    fn blocks() {
-        let mut s = String::new();
-        html!(s, {
-            ^{
-                let mut result = 1i32;
-                for i in 2..11 {
-                    result *= i;
-                }
-                result
-            }
-        }).unwrap();
-        assert_eq!(s, "3628800");
-    }
-
-    #[test]
-    fn attributes() {
-        let rocks = true;
-        let mut s = String::new();
-        html!(s, {
-            input checked?=true /
-            input checked?=false /
-            input checked?=rocks /
-            input checked?=(!rocks) /
-        }).unwrap();
-        assert_eq!(s, concat!(
-                r#"<input checked>"#,
-                r#"<input>"#,
-                r#"<input checked>"#,
-                r#"<input>"#));
-    }
-
-    static BEST_PONY: &'static str = "Pinkie Pie";
-
-    #[test]
-    fn statics() {
-        let mut s = String::new();
-        html!(s, ^BEST_PONY).unwrap();
-        assert_eq!(s, "Pinkie Pie");
-    }
-
-    #[test]
-    fn closures() {
-        let best_pony = "Pinkie Pie";
-        let mut s = String::new();
-        html!(s, ^best_pony).unwrap();
-        assert_eq!(s, "Pinkie Pie");
-    }
-
-    /// An example struct, for testing purposes only
-    struct Creature {
-        name: &'static str,
-        /// Rating out of 10, where:
-        /// * 0 is a naked mole rat with dysentery
-        /// * 10 is Sweetie Belle in a milkshake
-        adorableness: u32,
-    }
-
-    impl Creature {
-        fn repugnance(&self) -> u32 {
-            10 - self.adorableness
-        }
-    }
-
-    #[test]
-    fn structs() {
-        let pinkie = Creature {
-            name: "Pinkie Pie",
-            adorableness: 9,
-        };
-        let mut s = String::new();
-        html!(s, {
-            "Name: " ^pinkie.name ". Rating: " ^pinkie.repugnance()
-        }).unwrap();
-        assert_eq!(s, "Name: Pinkie Pie. Rating: 1");
-    }
-
-    #[test]
-    fn nested_macro_invocation() {
-        let best_pony = "Pinkie Pie";
-        let mut s = String::new();
-        html!(s, ^(format!("{}", best_pony))).unwrap();
-        assert_eq!(s, "Pinkie Pie");
-    }
-}
-
-#[test]
-fn issue_13() {
-    let owned = String::from("yay");
-    let mut s = String::new();
-    html!(s, ^owned).unwrap();
-    let _ = owned;
-}
-
-mod control {
-    #[test]
-    fn if_expr() {
-        for (number, &name) in (1..4).zip(["one", "two", "three"].iter()) {
-            let mut s = String::new();
-            html!(s, {
-                @if number == 1 {
-                    "one"
-                } @else if number == 2 {
-                    "two"
-                } @else if number == 3 {
-                    "three"
-                } @else {
-                    "oh noes"
-                }
-            }).unwrap();
-            assert_eq!(s, name);
-        }
-    }
-
-    #[test]
-    fn if_let() {
-        for &(input, output) in [(Some("yay"), "yay"), (None, "oh noes")].iter() {
-            let mut s = String::new();
-            html!(s, {
-                @if let Some(value) = input {
-                    ^value
-                } @else {
-                    "oh noes"
-                }
-            }).unwrap();
-            assert_eq!(s, output);
-        }
-    }
-
-    #[test]
-    fn for_expr() {
-        let ponies = ["Apple Bloom", "Scootaloo", "Sweetie Belle"];
-        let mut s = String::new();
-        html!(s, {
-            ul @for pony in &ponies {
-                li ^pony
-            }
-        }).unwrap();
-        assert_eq!(s, concat!(
-                "<ul>",
-                "<li>Apple Bloom</li>",
-                "<li>Scootaloo</li>",
-                "<li>Sweetie Belle</li>",
-                "</ul>"));
-    }
-
-    #[test]
-    fn match_expr() {
-        for &(input, output) in [(Some("yay"), "<div>yay</div>"), (None, "oh noes")].iter() {
-            let mut s = String::new();
-            html!(s, {
-                @match input {
-                  Some(value) => {
-                    div { ^value }
-                  },
-                  None => {
-                    "oh noes"
-                  },
-                }
-            }).unwrap();
-            assert_eq!(s, output);
-        }
-    }
-
-    #[test]
-    fn match_expr_without_delims() {
-        for &(input, output) in [(Some("yay"), "yay"), (None, "<span>oh noes</span>")].iter() {
-            let mut s = String::new();
-            html!(s, {
-                @match input {
-                  Some(value) => ^value,
-                  None => span { "oh noes" },
-                }
-            }).unwrap();
-            assert_eq!(s, output);
-        }
-    }
-
-    #[test]
-    fn match_expr_with_guards() {
-        for &(input, output) in [(Some(1), "one"), (None, "none"), (Some(2), "2")].iter() {
-            let mut s = String::new();
-            html!(s, {
-                @match input {
-                  Some(value) if value == 1 => "one",
-                  Some(value) => ^value,
-                  None => "none",
-                }
-            }).unwrap();
-            assert_eq!(s, output);
-        }
-    }
-
-    #[test]
-    fn match_in_attribute() {
-        for &(input, output) in [(1, "<span class=\"one\">1</span>"), (2, "<span class=\"two\">2</span>"), (3, "<span class=\"many\">3</span>")].iter() {
-            let mut s = String::new();
-            html!(s, {
-                span class=@match input {
-                    1 => "one",
-                    2 => "two",
-                    _ => "many",
-                } { ^input }
-            }).unwrap();
-            assert_eq!(s, output);
-        }
-    }
-}
-
-#[test]
-fn html_utf8() {
-    let mut buf = vec![];
-    html_utf8!(buf, p "hello").unwrap();
-    assert_eq!(buf, b"<p>hello</p>");
-}
-
-mod issue_10 {
-    #[test]
-    fn hyphens_in_element_names() {
-        let mut s = String::new();
-        html!(s, custom-element {}).unwrap();
-        assert_eq!(s, "<custom-element></custom-element>");
-    }
-
-    #[test]
-    fn hyphens_in_attribute_names() {
-        let mut s = String::new();
-        html!(s, this sentence-is="false" of-course? {}).unwrap();
-        assert_eq!(s, r#"<this sentence-is="false" of-course></this>"#);
-    }
-}
-
-#[test]
-fn call() {
-    fn ducks(w: &mut fmt::Write) -> fmt::Result {
-        write!(w, "Ducks")
-    }
-    let mut s = String::new();
-    let swans = |yes|
-        if yes {
-            |w: &mut fmt::Write| write!(w, "Swans")
-        } else {
-            panic!("oh noes")
-        };
-    html!(s, {
-        @call ducks
-        @call (|w: &mut fmt::Write| write!(w, "Geese"))
-        @call swans(true)
-    }).unwrap();
-    assert_eq!(s, "DucksGeeseSwans");
-}
-
-#[test]
-fn issue_23() {
-    macro_rules! to_string {
-        ($($x:tt)*) => {{
-            let mut s = String::new();
-            html!(s, $($x)*).unwrap();
-            s
-        }}
-    }
-
-    let name = "Lyra";
-    let s = to_string!(p { "Hi, " ^name "!" });
-    assert_eq!(s, "<p>Hi, Lyra!</p>");
-}
-
-#[test]
-fn tuple_accessors() {
-    let mut s = String::new();
-    let a = ("ducks", "geese");
-    html!(s, { ^a.0 }).unwrap();
-    assert_eq!(s, "ducks");
-}
-
-#[test]
-fn splice_with_path() {
-    mod inner {
-        pub fn name() -> &'static str {
-            "Maud"
-        }
-    }
-
-    let mut s = String::new();
-    html!(s, ^inner::name()).unwrap();
-    assert_eq!(s, "Maud");
-}
-
-#[test]
-fn class_shorthand() {
-    let mut s = String::new();
-    html!(s, p { "Hi, " span.name { "Lyra" } "!" }).unwrap();
-    assert_eq!(s, "<p>Hi, <span class=\"name\">Lyra</span>!</p>");
-}
-
-#[test]
-fn class_shorthand_with_space() {
-    let mut s = String::new();
-    html!(s, p { "Hi, " span .name { "Lyra" } "!" }).unwrap();
-    assert_eq!(s, "<p>Hi, <span class=\"name\">Lyra</span>!</p>");
-}
-
-#[test]
-fn classes_shorthand() {
-    let mut s = String::new();
-    html!(s, p { "Hi, " span.name.here { "Lyra" } "!" }).unwrap();
-    assert_eq!(s, "<p>Hi, <span class=\"name here\">Lyra</span>!</p>");
-}
-
-#[test]
-fn classes_shorthand_with_space() {
-    let mut s = String::new();
-    html!(s, p { "Hi, " span .name .here { "Lyra" } "!" }).unwrap();
-    assert_eq!(s, "<p>Hi, <span class=\"name here\">Lyra</span>!</p>");
-}
-
-#[test]
-fn ids_shorthand() {
-    let mut s = String::new();
-    html!(s, p { "Hi, " span#thing { "Lyra" } "!" }).unwrap();
-    assert_eq!(s, "<p>Hi, <span id=\"thing\">Lyra</span>!</p>");
-}
-
-#[test]
-fn classes_attrs_ids_mixed_up() {
-    let mut s = String::new();
-    html!(s, p { "Hi, " span.name.here lang="en" #thing { "Lyra" } "!" }).unwrap();
-    assert_eq!(s, "<p>Hi, <span lang=\"en\" class=\"name here\" id=\"thing\">Lyra</span>!</p>");
-}
-
-#[test]
-fn multirender() {
-    struct R<'a>(&'a str);
-    impl<'a> maud::Render for R<'a> {
-        fn render(&self, w: &mut std::fmt::Write) -> std::fmt::Result {
-            w.write_str(self.0)
-        }
-    }
-
-    let mut s = String::new();
-    let r = R("pinkie ");
-    html!(s, ^r).unwrap();
-    html!(s, ^r).unwrap();
-    // R is not-Copyable so this shows that it will auto-ref splice arguments that implement Render.
-    assert_eq!(s, "pinkie pinkie ");
-}
-
-#[test]
-fn render_once_by_move() {
-    struct Once<'a>(&'a str);
-    impl<'a> maud::RenderOnce for Once<'a> {
-        fn render_once(self, w: &mut std::fmt::Write) -> std::fmt::Result {
-            w.write_str(self.0)
-        }
-    }
-
-    let mut s = String::new();
-    let once = Once("pinkie");
-    html!(s, ^once).unwrap();
-    assert_eq!(s, "pinkie");
-}
-
-#[test]
-fn render_once_by_move_with_copy() {
-    #[derive(Clone, Copy)]
-    struct Once<'a>(&'a str);
-    impl<'a> maud::RenderOnce for Once<'a> {
-        fn render_once(self, w: &mut std::fmt::Write) -> std::fmt::Result {
-            w.write_str(self.0)
-        }
-    }
-
-    let mut s = String::new();
-    let once = Once("pinkie ");
-    html!(s, ^once).unwrap();
-    html!(s, ^once).unwrap();
-    assert_eq!(s, "pinkie pinkie ");
-}
-
-#[test]
-fn issue_26() {
-    macro_rules! to_string {
-        ($($x:tt)*) => {{
-            let mut s = String::new();
-            html!(s, $($x)*).unwrap();
-            s
-        }}
-    }
-
-    let name = "Lyra";
-    let s = to_string!(p { "Hi, " ^(name) "!" });
-    assert_eq!(s, "<p>Hi, Lyra!</p>");
-}
-
-#[test]
-fn issue_26_2() {
-    macro_rules! to_string {
-        ($($x:tt)*) => {{
-            let mut s = String::new();
-            html!(s, $($x)*).unwrap();
-            s
-        }}
-    }
-
-    let name = "Lyra";
-    let s = to_string!(p { "Hi, " ^("person called ".to_string() + name) "!" });
-    assert_eq!(s, "<p>Hi, person called Lyra!</p>");
-}
-
-#[test]
-fn issue_26_3() {
-    macro_rules! to_string {
-        ($($x:tt)*) => {{
-            let mut s = String::new();
-            html!(s, $($x)*).unwrap();
-            s
-        }}
-    }
-
-    let name = "Lyra";
-    let s = to_string!(p { "Hi, " ^{"person called ".to_string() + name} "!" });
-    assert_eq!(s, "<p>Hi, person called Lyra!</p>");
-}
-
-#[test]
-fn issue_21() {
-    macro_rules! greet {
-        () => ({
-            let mut result = String::new();
-            let name = "Pinkie Pie";
-            html!(result, p { "Hello, " ^name "!" }).map(|()| result)
-        })
-    }
-
-    let s = greet!().unwrap();
-    assert_eq!(s, "<p>Hello, Pinkie Pie!</p>");
-}
-
-#[test]
-fn issue_21_2() {
-    macro_rules! greet {
-        ($name:expr) => ({
-            let mut result = String::new();
-            html!(result, p { "Hello, " ^$name "!" }).map(|()| result)
-        })
-    }
-
-    let s = greet!("Pinkie Pie").unwrap();
-    assert_eq!(s, "<p>Hello, Pinkie Pie!</p>");
-}