webdriver: Add support to format values with {:?} (#111)
authorHenrik Skupin <hskupin@mozilla.com>
Tue, 08 Aug 2017 11:14:55 +0100
changeset 428161 9ed7cfbf72b2eef1baee42382f4e389cb55acd14
parent 428160 46d799fb047c56029dc38e6ff3d3234081d99ea9
child 428162 0f86628ff5db5712f540010e4b2f19a5711635c8
push id7761
push userjlund@mozilla.com
push dateFri, 15 Sep 2017 00:19:52 +0000
treeherdermozilla-beta@c38455951db4 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
milestone57.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
webdriver: Add support to format values with {:?} (#111) For debugging purposes it is helpful when enum and struct definitions are using derive Debug. Source-Repo: https://github.com/mozilla/webdriver-rust Source-Revision: 989cfcb7ab23ab356b2bf77ff37a37ab1c7be89d committer: jgraham <james@hoppipolla.co.uk>
testing/webdriver/src/command.rs
testing/webdriver/src/common.rs
testing/webdriver/src/error.rs
testing/webdriver/src/httpapi.rs
testing/webdriver/src/response.rs
testing/webdriver/src/server.rs
--- a/testing/webdriver/src/command.rs
+++ b/testing/webdriver/src/command.rs
@@ -4,17 +4,17 @@ use common::{Date, Nullable, WebElement,
 use error::{WebDriverResult, WebDriverError, ErrorStatus};
 use httpapi::{Route, WebDriverExtensionRoute, VoidWebDriverExtensionRoute};
 use regex::Captures;
 use rustc_serialize::json;
 use rustc_serialize::json::{ToJson, Json};
 use std::collections::BTreeMap;
 use std::default::Default;
 
-#[derive(PartialEq)]
+#[derive(Debug, PartialEq)]
 pub enum WebDriverCommand<T: WebDriverExtensionCommand> {
     NewSession(NewSessionParameters),
     DeleteSession,
     Get(GetParameters),
     GetCurrentUrl,
     GoBack,
     GoForward,
     Refresh,
@@ -69,26 +69,26 @@ pub enum WebDriverCommand<T: WebDriverEx
     Status,
     Extension(T)
 }
 
 pub trait WebDriverExtensionCommand : Clone + Send + PartialEq {
     fn parameters_json(&self) -> Option<Json>;
 }
 
-#[derive(Clone, PartialEq)]
+#[derive(Clone, Debug, PartialEq)]
 pub struct VoidWebDriverExtensionCommand;
 
 impl WebDriverExtensionCommand for VoidWebDriverExtensionCommand {
     fn parameters_json(&self) -> Option<Json> {
         panic!("No extensions implemented");
     }
 }
 
-#[derive(PartialEq)]
+#[derive(Debug, PartialEq)]
 pub struct WebDriverMessage <U: WebDriverExtensionRoute=VoidWebDriverExtensionRoute> {
     pub session_id: Option<String>,
     pub command: WebDriverCommand<U::Command>,
 }
 
 impl<U: WebDriverExtensionRoute> WebDriverMessage<U> {
     pub fn new(session_id: Option<String>,
                command: WebDriverCommand<U::Command>)
@@ -485,17 +485,17 @@ impl CapabilitiesMatching for NewSession
         match self {
             &NewSessionParameters::Spec(ref x) => x.match_browser(browser_capabilities),
             &NewSessionParameters::Legacy(ref x) => x.match_browser(browser_capabilities)
         }
     }
 }
 
 
-#[derive(PartialEq)]
+#[derive(Debug, PartialEq)]
 pub struct GetParameters {
     pub url: String
 }
 
 impl Parameters for GetParameters {
     fn from_json(body: &Json) -> WebDriverResult<GetParameters> {
         let data = try_opt!(body.as_object(), ErrorStatus::UnknownError,
                             "Message body was not an object");
@@ -514,17 +514,17 @@ impl Parameters for GetParameters {
 impl ToJson for GetParameters {
     fn to_json(&self) -> Json {
         let mut data = BTreeMap::new();
         data.insert("url".to_string(), self.url.to_json());
         Json::Object(data)
     }
 }
 
-#[derive(PartialEq)]
+#[derive(Debug, PartialEq)]
 pub struct TimeoutsParameters {
     pub script: Option<u64>,
     pub page_load: Option<u64>,
     pub implicit: Option<u64>,
 }
 
 impl Parameters for TimeoutsParameters {
     fn from_json(body: &Json) -> WebDriverResult<TimeoutsParameters> {
@@ -653,17 +653,17 @@ impl ToJson for WindowRectParameters {
         data.insert("x".to_string(), self.x.to_json());
         data.insert("y".to_string(), self.y.to_json());
         data.insert("width".to_string(), self.width.to_json());
         data.insert("height".to_string(), self.height.to_json());
         Json::Object(data)
     }
 }
 
-#[derive(PartialEq)]
+#[derive(Debug, PartialEq)]
 pub struct SwitchToWindowParameters {
     pub handle: String
 }
 
 impl Parameters for SwitchToWindowParameters {
     fn from_json(body: &Json) -> WebDriverResult<SwitchToWindowParameters> {
         let data = try_opt!(body.as_object(), ErrorStatus::UnknownError,
                             "Message body was not an object");
@@ -682,17 +682,17 @@ impl Parameters for SwitchToWindowParame
 impl ToJson for SwitchToWindowParameters {
     fn to_json(&self) -> Json {
         let mut data = BTreeMap::new();
         data.insert("handle".to_string(), self.handle.to_json());
         Json::Object(data)
     }
 }
 
-#[derive(PartialEq)]
+#[derive(Debug, PartialEq)]
 pub struct LocatorParameters {
     pub using: LocatorStrategy,
     pub value: String
 }
 
 impl Parameters for LocatorParameters {
     fn from_json(body: &Json) -> WebDriverResult<LocatorParameters> {
         let data = try_opt!(body.as_object(), ErrorStatus::UnknownError,
@@ -721,17 +721,17 @@ impl ToJson for LocatorParameters {
     fn to_json(&self) -> Json {
         let mut data = BTreeMap::new();
         data.insert("using".to_string(), self.using.to_json());
         data.insert("value".to_string(), self.value.to_json());
         Json::Object(data)
     }
 }
 
-#[derive(PartialEq)]
+#[derive(Debug, PartialEq)]
 pub struct SwitchToFrameParameters {
     pub id: FrameId
 }
 
 impl Parameters for SwitchToFrameParameters {
     fn from_json(body: &Json) -> WebDriverResult<SwitchToFrameParameters> {
         let data = try_opt!(body.as_object(),
                             ErrorStatus::UnknownError,
@@ -749,17 +749,17 @@ impl Parameters for SwitchToFrameParamet
 impl ToJson for SwitchToFrameParameters {
     fn to_json(&self) -> Json {
         let mut data = BTreeMap::new();
         data.insert("id".to_string(), self.id.to_json());
         Json::Object(data)
     }
 }
 
-#[derive(PartialEq)]
+#[derive(Debug, PartialEq)]
 pub struct SendKeysParameters {
     pub text: String
 }
 
 impl Parameters for SendKeysParameters {
     fn from_json(body: &Json) -> WebDriverResult<SendKeysParameters> {
         let data = try_opt!(body.as_object(),
                             ErrorStatus::InvalidArgument,
@@ -779,17 +779,17 @@ impl Parameters for SendKeysParameters {
 impl ToJson for SendKeysParameters {
     fn to_json(&self) -> Json {
         let mut data = BTreeMap::new();
         data.insert("value".to_string(), self.text.to_json());
         Json::Object(data)
     }
 }
 
-#[derive(PartialEq)]
+#[derive(Debug, PartialEq)]
 pub struct JavascriptCommandParameters {
     pub script: String,
     pub args: Nullable<Vec<Json>>
 }
 
 impl Parameters for JavascriptCommandParameters {
     fn from_json(body: &Json) -> WebDriverResult<JavascriptCommandParameters> {
         let data = try_opt!(body.as_object(),
@@ -827,17 +827,17 @@ impl ToJson for JavascriptCommandParamet
         let mut data = BTreeMap::new();
         //TODO: Wrap script so that it becomes marionette-compatible
         data.insert("script".to_string(), self.script.to_json());
         data.insert("args".to_string(), self.args.to_json());
         Json::Object(data)
     }
 }
 
-#[derive(PartialEq)]
+#[derive(Debug, PartialEq)]
 pub struct GetNamedCookieParameters {
     pub name: Nullable<String>,
 }
 
 impl Parameters for GetNamedCookieParameters {
     fn from_json(body: &Json) -> WebDriverResult<GetNamedCookieParameters> {
         let data = try_opt!(body.as_object(),
                             ErrorStatus::InvalidArgument,
@@ -858,17 +858,17 @@ impl Parameters for GetNamedCookieParame
 impl ToJson for GetNamedCookieParameters {
     fn to_json(&self) -> Json {
         let mut data = BTreeMap::new();
         data.insert("name".to_string(), self.name.to_json());
         Json::Object(data)
     }
 }
 
-#[derive(PartialEq)]
+#[derive(Debug, PartialEq)]
 pub struct AddCookieParameters {
     pub name: String,
     pub value: String,
     pub path: Nullable<String>,
     pub domain: Nullable<String>,
     pub expiry: Nullable<Date>,
     pub secure: bool,
     pub httpOnly: bool
@@ -973,17 +973,17 @@ impl ToJson for AddCookieParameters {
         data.insert("domain".to_string(), self.domain.to_json());
         data.insert("expiry".to_string(), self.expiry.to_json());
         data.insert("secure".to_string(), self.secure.to_json());
         data.insert("httpOnly".to_string(), self.httpOnly.to_json());
         Json::Object(data)
     }
 }
 
-#[derive(PartialEq)]
+#[derive(Debug, PartialEq)]
 pub struct TakeScreenshotParameters {
     pub element: Nullable<WebElement>
 }
 
 impl Parameters for TakeScreenshotParameters {
     fn from_json(body: &Json) -> WebDriverResult<TakeScreenshotParameters> {
         let data = try_opt!(body.as_object(),
                             ErrorStatus::InvalidArgument,
@@ -1006,17 +1006,17 @@ impl Parameters for TakeScreenshotParame
 impl ToJson for TakeScreenshotParameters {
     fn to_json(&self) -> Json {
         let mut data = BTreeMap::new();
         data.insert("element".to_string(), self.element.to_json());
         Json::Object(data)
     }
 }
 
-#[derive(PartialEq)]
+#[derive(Debug, PartialEq)]
 pub struct ActionsParameters {
     pub actions: Vec<ActionSequence>
 }
 
 impl Parameters for ActionsParameters {
     fn from_json(body: &Json) -> WebDriverResult<ActionsParameters> {
         try_opt!(body.as_object(),
                  ErrorStatus::InvalidArgument,
@@ -1042,17 +1042,17 @@ impl ToJson for ActionsParameters {
     fn to_json(&self) -> Json {
         let mut data = BTreeMap::new();
         data.insert("actions".to_owned(),
                     self.actions.iter().map(|x| x.to_json()).collect::<Vec<Json>>().to_json());
         Json::Object(data)
     }
 }
 
-#[derive(PartialEq)]
+#[derive(Debug, PartialEq)]
 pub struct ActionSequence {
     pub id: Nullable<String>,
     pub actions: ActionsType
 }
 
 impl Parameters for ActionSequence {
     fn from_json(body: &Json) -> WebDriverResult<ActionSequence> {
         let data = try_opt!(body.as_object(),
@@ -1108,17 +1108,17 @@ impl ToJson for ActionSequence {
             }
         };
         data.insert("type".into(), action_type.to_json());
         data.insert("actions".into(), actions.to_json());
         Json::Object(data)
     }
 }
 
-#[derive(PartialEq)]
+#[derive(Debug, PartialEq)]
 pub enum ActionsType {
     Null(Vec<NullActionItem>),
     Key(Vec<KeyActionItem>),
     Pointer(PointerActionParameters, Vec<PointerActionItem>)
 }
 
 impl Parameters for ActionsType {
     fn from_json(body: &Json) -> WebDriverResult<ActionsType> {
@@ -1157,17 +1157,17 @@ impl Parameters for ActionsType {
                 }
                 Ok(ActionsType::Pointer(parameters, actions))
             }
             _ => panic!("Got unexpected action type after checking type")
         }
     }
 }
 
-#[derive(PartialEq)]
+#[derive(Debug, PartialEq)]
 pub enum PointerType {
     Mouse,
     Pen,
     Touch,
 }
 
 impl Parameters for PointerType {
     fn from_json(body: &Json) -> WebDriverResult<PointerType> {
@@ -1198,17 +1198,17 @@ impl ToJson for PointerType {
 }
 
 impl Default for PointerType {
     fn default() -> PointerType {
         PointerType::Mouse
     }
 }
 
-#[derive(Default, PartialEq)]
+#[derive(Debug, Default, PartialEq)]
 pub struct PointerActionParameters {
     pub pointer_type: PointerType
 }
 
 impl Parameters for PointerActionParameters {
     fn from_json(body: &Json) -> WebDriverResult<PointerActionParameters> {
         let data = try_opt!(body.as_object(),
                             ErrorStatus::InvalidArgument,
@@ -1227,17 +1227,17 @@ impl ToJson for PointerActionParameters 
     fn to_json(&self) -> Json {
         let mut data = BTreeMap::new();
         data.insert("pointerType".to_owned(),
                     self.pointer_type.to_json());
         Json::Object(data)
     }
 }
 
-#[derive(PartialEq)]
+#[derive(Debug, PartialEq)]
 pub enum NullActionItem {
     General(GeneralAction)
 }
 
 impl Parameters for NullActionItem {
     fn from_json(body: &Json) -> WebDriverResult<NullActionItem> {
         let data = try_opt!(body.as_object(),
                             ErrorStatus::InvalidArgument,
@@ -1260,17 +1260,17 @@ impl Parameters for NullActionItem {
 impl ToJson for NullActionItem {
     fn to_json(&self) -> Json {
         match self {
             &NullActionItem::General(ref x) => x.to_json(),
         }
     }
 }
 
-#[derive(PartialEq)]
+#[derive(Debug, PartialEq)]
 pub enum KeyActionItem {
     General(GeneralAction),
     Key(KeyAction)
 }
 
 impl Parameters for KeyActionItem {
     fn from_json(body: &Json) -> WebDriverResult<KeyActionItem> {
         let data = try_opt!(body.as_object(),
@@ -1295,17 +1295,17 @@ impl ToJson for KeyActionItem {
     fn to_json(&self) -> Json {
         match *self {
             KeyActionItem::General(ref x) => x.to_json(),
             KeyActionItem::Key(ref x) => x.to_json()
         }
     }
 }
 
-#[derive(PartialEq)]
+#[derive(Debug, PartialEq)]
 pub enum PointerActionItem {
     General(GeneralAction),
     Pointer(PointerAction)
 }
 
 impl Parameters for PointerActionItem {
     fn from_json(body: &Json) -> WebDriverResult<PointerActionItem> {
         let data = try_opt!(body.as_object(),
@@ -1329,17 +1329,17 @@ impl ToJson for PointerActionItem {
     fn to_json(&self) -> Json {
         match self {
             &PointerActionItem::General(ref x) => x.to_json(),
             &PointerActionItem::Pointer(ref x) => x.to_json()
         }
     }
 }
 
-#[derive(PartialEq)]
+#[derive(Debug, PartialEq)]
 pub enum GeneralAction {
     Pause(PauseAction)
 }
 
 impl Parameters for GeneralAction {
     fn from_json(body: &Json) -> WebDriverResult<GeneralAction> {
         match body.find("type").and_then(|x| x.as_string()) {
             Some("pause") => Ok(GeneralAction::Pause(try!(PauseAction::from_json(body)))),
@@ -1352,17 +1352,17 @@ impl Parameters for GeneralAction {
 impl ToJson for GeneralAction {
     fn to_json(&self) -> Json {
         match self {
             &GeneralAction::Pause(ref x) => x.to_json()
         }
     }
 }
 
-#[derive(PartialEq)]
+#[derive(Debug, PartialEq)]
 pub struct PauseAction {
     pub duration: u64
 }
 
 impl Parameters for PauseAction {
     fn from_json(body: &Json) -> WebDriverResult<PauseAction> {
         let default = Json::U64(0);
         Ok(PauseAction {
@@ -1379,17 +1379,17 @@ impl ToJson for PauseAction {
         data.insert("type".to_owned(),
                     "pause".to_json());
         data.insert("duration".to_owned(),
                     self.duration.to_json());
         Json::Object(data)
     }
 }
 
-#[derive(PartialEq)]
+#[derive(Debug, PartialEq)]
 pub enum KeyAction {
     Up(KeyUpAction),
     Down(KeyDownAction)
 }
 
 impl Parameters for KeyAction {
     fn from_json(body: &Json) -> WebDriverResult<KeyAction> {
         match body.find("type").and_then(|x| x.as_string()) {
@@ -1422,17 +1422,17 @@ fn validate_key_value(value_str: &str) -
     if chars.next().is_some() {
         return Err(WebDriverError::new(
             ErrorStatus::InvalidArgument,
             "Parameter 'value' contained multiple characters"))
     };
     Ok(value)
 }
 
-#[derive(PartialEq)]
+#[derive(Debug, PartialEq)]
 pub struct KeyUpAction {
     pub value: char
 }
 
 impl Parameters for KeyUpAction {
     fn from_json(body: &Json) -> WebDriverResult<KeyUpAction> {
         let value_str = try_opt!(
                 try_opt!(body.find("value"),
@@ -1454,17 +1454,17 @@ impl ToJson for KeyUpAction {
         data.insert("type".to_owned(),
                     "keyUp".to_json());
         data.insert("value".to_string(),
                     self.value.to_string().to_json());
         Json::Object(data)
     }
 }
 
-#[derive(PartialEq)]
+#[derive(Debug, PartialEq)]
 pub struct KeyDownAction {
     pub value: char
 }
 
 impl Parameters for KeyDownAction {
     fn from_json(body: &Json) -> WebDriverResult<KeyDownAction> {
         let value_str = try_opt!(
                 try_opt!(body.find("value"),
@@ -1485,17 +1485,17 @@ impl ToJson for KeyDownAction {
         data.insert("type".to_owned(),
                     "keyDown".to_json());
         data.insert("value".to_owned(),
                     self.value.to_string().to_json());
         Json::Object(data)
     }
 }
 
-#[derive(PartialEq)]
+#[derive(Debug, PartialEq)]
 pub enum PointerOrigin {
     Viewport,
     Pointer,
     Element(WebElement),
 }
 
 impl Parameters for PointerOrigin {
     fn from_json(body: &Json) -> WebDriverResult<PointerOrigin> {
@@ -1526,17 +1526,17 @@ impl ToJson for PointerOrigin {
 }
 
 impl Default for PointerOrigin {
     fn default() -> PointerOrigin {
         PointerOrigin::Viewport
     }
 }
 
-#[derive(PartialEq)]
+#[derive(Debug, PartialEq)]
 pub enum PointerAction {
     Up(PointerUpAction),
     Down(PointerDownAction),
     Move(PointerMoveAction),
     Cancel
 }
 
 impl Parameters for PointerAction {
@@ -1564,17 +1564,17 @@ impl ToJson for PointerAction {
                 data.insert("type".to_owned(),
                             "pointerCancel".to_json());
                 Json::Object(data)
             }
         }
     }
 }
 
-#[derive(PartialEq)]
+#[derive(Debug, PartialEq)]
 pub struct PointerUpAction {
     pub button: u64,
 }
 
 impl Parameters for PointerUpAction {
     fn from_json(body: &Json) -> WebDriverResult<PointerUpAction> {
         let button = try_opt!(
             try_opt!(body.find("button"),
@@ -1594,17 +1594,17 @@ impl ToJson for PointerUpAction {
         let mut data = BTreeMap::new();
         data.insert("type".to_owned(),
                     "pointerUp".to_json());
         data.insert("button".to_owned(), self.button.to_json());
         Json::Object(data)
     }
 }
 
-#[derive(PartialEq)]
+#[derive(Debug, PartialEq)]
 pub struct PointerDownAction {
     pub button: u64,
 }
 
 impl Parameters for PointerDownAction {
     fn from_json(body: &Json) -> WebDriverResult<PointerDownAction> {
         let button = try_opt!(
             try_opt!(body.find("button"),
@@ -1624,17 +1624,17 @@ impl ToJson for PointerDownAction {
         let mut data = BTreeMap::new();
         data.insert("type".to_owned(),
                     "pointerDown".to_json());
         data.insert("button".to_owned(), self.button.to_json());
         Json::Object(data)
     }
 }
 
-#[derive(PartialEq)]
+#[derive(Debug, PartialEq)]
 pub struct PointerMoveAction {
     pub duration: Nullable<u64>,
     pub origin: PointerOrigin,
     pub x: Nullable<i64>,
     pub y: Nullable<i64>
 }
 
 impl Parameters for PointerMoveAction {
--- a/testing/webdriver/src/common.rs
+++ b/testing/webdriver/src/common.rs
@@ -1,33 +1,33 @@
 use rustc_serialize::{Encodable, Encoder};
 use rustc_serialize::json::{Json, ToJson};
 use std::collections::BTreeMap;
 
 use error::{WebDriverResult, WebDriverError, ErrorStatus};
 
 pub static ELEMENT_KEY: &'static str = "element-6066-11e4-a52e-4f735466cecf";
 
-#[derive(RustcEncodable, PartialEq, Clone, Debug)]
+#[derive(Clone, Debug, PartialEq, RustcEncodable)]
 pub struct Date(pub u64);
 
 impl Date {
     pub fn new(timestamp: u64) -> Date {
         Date(timestamp)
     }
 }
 
 impl ToJson for Date {
     fn to_json(&self) -> Json {
         let &Date(x) = self;
         x.to_json()
     }
 }
 
-#[derive(PartialEq, Clone, Debug)]
+#[derive(Clone, Debug, PartialEq)]
 pub enum Nullable<T: ToJson> {
     Value(T),
     Null
 }
 
 impl<T: ToJson> Nullable<T> {
      pub fn is_null(&self) -> bool {
         match *self {
@@ -137,17 +137,17 @@ impl ToJson for WebElement {
 
 impl <T> From<T> for WebElement
     where T: Into<String> {
     fn from(data: T) -> WebElement {
         WebElement::new(data.into())
     }
 }
 
-#[derive(PartialEq, Debug)]
+#[derive(Debug, PartialEq)]
 pub enum FrameId {
     Short(u16),
     Element(WebElement),
     Null
 }
 
 impl FrameId {
     pub fn from_json(data: &Json) -> WebDriverResult<FrameId> {
@@ -179,17 +179,17 @@ impl ToJson for FrameId {
             },
             FrameId::Null => {
                 Json::Null
             }
         }
     }
 }
 
-#[derive(PartialEq)]
+#[derive(Debug, PartialEq)]
 pub enum LocatorStrategy {
     CSSSelector,
     LinkText,
     PartialLinkText,
     XPath,
 }
 
 impl LocatorStrategy {
--- a/testing/webdriver/src/error.rs
+++ b/testing/webdriver/src/error.rs
@@ -4,17 +4,17 @@ use rustc_serialize::base64::FromBase64E
 use rustc_serialize::json::{DecoderError, Json, ParserError, ToJson};
 use std::borrow::Cow;
 use std::collections::BTreeMap;
 use std::convert::From;
 use std::error::Error;
 use std::fmt;
 use std::io;
 
-#[derive(PartialEq, Debug)]
+#[derive(Debug, PartialEq)]
 pub enum ErrorStatus {
     /// The [`ElementClick`] command could not be completed because the
     /// [element] receiving the events is obscuring the element that was
     /// requested clicked.
     ///
     /// [`ElementClick`]:
     /// ../command/enum.WebDriverCommand.html#variant.ElementClick
     /// [element]: ../common/struct.WebElement.html
--- a/testing/webdriver/src/httpapi.rs
+++ b/testing/webdriver/src/httpapi.rs
@@ -66,17 +66,17 @@ fn standard_routes<U:WebDriverExtensionR
                 (Post, "/session/{sessionId}/alert/text", Route::SendAlertText),
                 (Get, "/session/{sessionId}/screenshot", Route::TakeScreenshot),
                 (Get, "/session/{sessionId}/element/{elementId}/screenshot", Route::TakeElementScreenshot),
                 (Post, "/session/{sessionId}/actions", Route::PerformActions),
                 (Delete, "/session/{sessionId}/actions", Route::ReleaseActions),
                 (Get, "/status", Route::Status),]
 }
 
-#[derive(Clone, Copy)]
+#[derive(Clone, Copy, Debug)]
 pub enum Route<U:WebDriverExtensionRoute> {
     NewSession,
     DeleteSession,
     Get,
     GetCurrentUrl,
     GoBack,
     GoForward,
     Refresh,
@@ -137,28 +137,28 @@ pub enum Route<U:WebDriverExtensionRoute
 }
 
 pub trait WebDriverExtensionRoute : Clone + Send + PartialEq {
     type Command: WebDriverExtensionCommand + 'static;
 
     fn command(&self, &Captures, &Json) -> WebDriverResult<WebDriverCommand<Self::Command>>;
 }
 
-#[derive(Clone, PartialEq)]
+#[derive(Clone, Debug, PartialEq)]
 pub struct VoidWebDriverExtensionRoute;
 
 impl WebDriverExtensionRoute for VoidWebDriverExtensionRoute {
     type Command = VoidWebDriverExtensionCommand;
 
     fn command(&self, _:&Captures, _:&Json) -> WebDriverResult<WebDriverCommand<VoidWebDriverExtensionCommand>> {
         panic!("No extensions implemented");
     }
 }
 
-#[derive(Clone)]
+#[derive(Clone, Debug)]
 struct RequestMatcher<U: WebDriverExtensionRoute> {
     method: Method,
     path_regexp: Regex,
     match_type: Route<U>
 }
 
 impl <U: WebDriverExtensionRoute> RequestMatcher<U> {
     pub fn new(method: Method, path: &str, match_type: Route<U>) -> RequestMatcher<U> {
@@ -192,16 +192,17 @@ impl <U: WebDriverExtensionRoute> Reques
         //Remove the trailing /
         rv.pop();
         rv.push_str("$");
         //This will fail at runtime if the regexp is invalid
         Regex::new(&rv[..]).unwrap()
     }
 }
 
+#[derive(Debug)]
 pub struct WebDriverHttpApi<U: WebDriverExtensionRoute> {
     routes: Vec<(Method, RequestMatcher<U>)>,
 }
 
 impl <U: WebDriverExtensionRoute> WebDriverHttpApi<U> {
     pub fn new(extension_routes: &[(Method, &str, U)]) -> WebDriverHttpApi<U> {
         let mut rv = WebDriverHttpApi::<U> {
             routes: vec![],
--- a/testing/webdriver/src/response.rs
+++ b/testing/webdriver/src/response.rs
@@ -43,17 +43,17 @@ impl WebDriverResponse {
                 data.push_str(&*obj);
                 data.push_str("}");
                 data
             }
         }
     }
 }
 
-#[derive(RustcEncodable, Debug)]
+#[derive(Debug, RustcEncodable)]
 pub struct CloseWindowResponse {
     pub window_handles: Vec<String>,
 }
 
 impl CloseWindowResponse {
     pub fn new(handles: Vec<String>) -> CloseWindowResponse {
         CloseWindowResponse { window_handles: handles }
     }
@@ -63,62 +63,62 @@ impl ToJson for CloseWindowResponse {
     fn to_json(&self) -> Json {
         Json::Array(self.window_handles
                     .iter()
                     .map(|x| Json::String(x.clone()))
                     .collect::<Vec<Json>>())
     }
 }
 
-#[derive(RustcEncodable, Debug)]
+#[derive(Debug, RustcEncodable)]
 pub struct NewSessionResponse {
     pub sessionId: String,
     pub capabilities: json::Json
 }
 
 impl NewSessionResponse {
     pub fn new(session_id: String, capabilities: json::Json) -> NewSessionResponse {
         NewSessionResponse {
             capabilities: capabilities,
             sessionId: session_id
         }
     }
 }
 
-#[derive(RustcEncodable, Debug)]
+#[derive(Debug, RustcEncodable)]
 pub struct TimeoutsResponse {
     pub script: u64,
     pub pageLoad: u64,
     pub implicit: u64,
 }
 
 impl TimeoutsResponse {
     pub fn new(script: u64, page_load: u64, implicit: u64) -> TimeoutsResponse {
         TimeoutsResponse {
             script: script,
             pageLoad: page_load,
             implicit: implicit,
         }
     }
 }
 
-#[derive(RustcEncodable, Debug)]
+#[derive(Debug, RustcEncodable)]
 pub struct ValueResponse {
     pub value: json::Json
 }
 
 impl ValueResponse {
     pub fn new(value: json::Json) -> ValueResponse {
         ValueResponse {
             value: value
         }
     }
 }
 
-#[derive(RustcEncodable, Debug)]
+#[derive(Debug, RustcEncodable)]
 pub struct ElementRectResponse {
     /// X axis position of the top-left corner of the element relative
     // to the current browsing context’s document element in CSS reference
     // pixels.
     pub x: f64,
 
     /// Y axis position of the top-left corner of the element relative
     // to the current browsing context’s document element in CSS reference
@@ -171,17 +171,17 @@ impl ToJson for WindowRectResponse {
         body.insert("y".to_owned(), self.y.to_json());
         body.insert("width".to_owned(), self.width.to_json());
         body.insert("height".to_owned(), self.height.to_json());
         body.insert("state".to_owned(), self.state.to_json());
         Json::Object(body)
     }
 }
 
-#[derive(RustcEncodable, PartialEq, Debug, Clone)]
+#[derive(Clone, Debug, PartialEq, RustcEncodable)]
 pub struct Cookie {
     pub name: String,
     pub value: String,
     pub path: Nullable<String>,
     pub domain: Nullable<String>,
     pub expiry: Nullable<Date>,
     pub secure: bool,
     pub httpOnly: bool,
@@ -205,22 +205,22 @@ impl Into<cookie::Cookie<'static>> for C
                 cookie.expires(time::at(time::Timespec::new(expiry as i64, 0)))
             }
             Nullable::Null => cookie,
         };
         cookie.finish()
     }
 }
 
-#[derive(RustcEncodable, Debug)]
+#[derive(Debug, RustcEncodable)]
 pub struct CookieResponse {
     pub value: Cookie,
 }
 
-#[derive(RustcEncodable, Debug)]
+#[derive(Debug, RustcEncodable)]
 pub struct CookiesResponse {
     pub value: Vec<Cookie>,
 }
 
 #[cfg(test)]
 mod tests {
     use super::{CloseWindowResponse, Cookie, CookieResponse, CookiesResponse, ElementRectResponse,
                 NewSessionResponse, Nullable, TimeoutsResponse, ValueResponse, WebDriverResponse,
--- a/testing/webdriver/src/server.rs
+++ b/testing/webdriver/src/server.rs
@@ -18,17 +18,17 @@ use error::{WebDriverResult, WebDriverEr
 use httpapi::{WebDriverHttpApi, WebDriverExtensionRoute, VoidWebDriverExtensionRoute};
 use response::{CloseWindowResponse, WebDriverResponse};
 
 enum DispatchMessage<U: WebDriverExtensionRoute> {
     HandleWebDriver(WebDriverMessage<U>, Sender<WebDriverResult<WebDriverResponse>>),
     Quit
 }
 
-#[derive(PartialEq, Clone)]
+#[derive(Clone, Debug, PartialEq)]
 pub struct Session {
     id: String
 }
 
 impl Session {
     fn new(id: String) -> Session {
         Session {
             id: id
@@ -36,16 +36,17 @@ impl Session {
     }
 }
 
 pub trait WebDriverHandler<U: WebDriverExtensionRoute=VoidWebDriverExtensionRoute> : Send {
     fn handle_command(&mut self, session: &Option<Session>, msg: WebDriverMessage<U>) -> WebDriverResult<WebDriverResponse>;
     fn delete_session(&mut self, session: &Option<Session>);
 }
 
+#[derive(Debug)]
 struct Dispatcher<T: WebDriverHandler<U>,
                   U: WebDriverExtensionRoute> {
     handler: T,
     session: Option<Session>,
     extension_type: PhantomData<U>,
 }
 
 impl<T: WebDriverHandler<U>, U: WebDriverExtensionRoute> Dispatcher<T, U> {
@@ -143,16 +144,17 @@ impl<T: WebDriverHandler<U>, U: WebDrive
                         }
                     }
                 }
             }
         }
     }
 }
 
+#[derive(Debug)]
 struct HttpHandler<U: WebDriverExtensionRoute> {
     chan: Mutex<Sender<DispatchMessage<U>>>,
     api: Mutex<WebDriverHttpApi<U>>
 }
 
 impl <U: WebDriverExtensionRoute> HttpHandler<U> {
     fn new(api: WebDriverHttpApi<U>, chan: Sender<DispatchMessage<U>>) -> HttpHandler<U> {
         HttpHandler {