Repository: cdent/gabbi

Issue:
response_string can lead to false positives if value is a string
The correct way to do the `response_strings` test is to provide a list of strings:

```yaml
response_strings:
    - foo
    - bar
```

If you forget and do a string, though, it can sometimes pass because the value is use as an iterable and strings iterate. In the following example of the response contains the letters `f` and `o` the test will pass:

```yaml
response_strings:
    foo
```

Stronger type checking is required.

Discussion:

Patch:
diff --git a/gabbi/handlers/base.py b/gabbi/handlers/base.py
index 03c37e3..055aff8 100644
--- a/gabbi/handlers/base.py
+++ b/gabbi/handlers/base.py
@@ -13,6 +13,9 @@
 """Base classes for response and content handlers."""
 
 
+from gabbi.exception import GabbiFormatError
+
+
 class ResponseHandler(object):
     """Add functionality for making assertions about an HTTP response.
 
@@ -38,6 +41,11 @@ class ResponseHandler(object):
     def __call__(self, test):
         if test.test_data[self._key]:
             self.preprocess(test)
+            if type(self.test_key_value) != type(test.test_data[self._key]):
+                raise GabbiFormatError(
+                    "%s in '%s' has incorrect type, must be %s"
+                    % (self._key, test.test_data['name'],
+                       type(self.test_key_value)))
             for item in test.test_data[self._key]:
                 try:
                     value = test.test_data[self._key][item]


Test patch:
diff --git a/gabbi/tests/test_handlers.py b/gabbi/tests/test_handlers.py
index df655b4..3caa086 100644
--- a/gabbi/tests/test_handlers.py
+++ b/gabbi/tests/test_handlers.py
@@ -17,6 +17,7 @@ import json
 import unittest
 
 from gabbi import case
+from gabbi.exception import GabbiFormatError
 from gabbi.handlers import core
 from gabbi.handlers import jsonhandler
 from gabbi import suitemaker
@@ -104,6 +105,19 @@ class HandlersTest(unittest.TestCase):
         # Check the pprint of the json
         self.assertIn('      "location": "house"', msg)
 
+    def test_response_string_list_type(self):
+        handler = core.StringResponseHandler()
+        self.test.test_data = {
+            'name': 'omega test',
+            'response_strings': 'omega'
+        }
+        self.test.output = 'omega\n'
+        with self.assertRaises(GabbiFormatError) as exc:
+            self._assert_handler(handler)
+            self.assertIn('has incorrect type', str(exc))
+            self.assertIn("response_strings in 'omega test'",
+                          str(exc))
+
     def test_response_json_paths(self):
         handler = jsonhandler.JSONHandler()
         self.test.content_type = "application/json"
@@ -178,6 +192,19 @@ class HandlersTest(unittest.TestCase):
         }
         self._assert_handler(handler)
 
+    def test_response_json_paths_dict_type(self):
+        handler = jsonhandler.JSONHandler()
+        self.test.test_data = {
+            'name': 'omega test',
+            'response_json_paths': ['alpha', 'beta']
+        }
+        self.test.output = 'omega\n'
+        with self.assertRaises(GabbiFormatError) as exc:
+            self._assert_handler(handler)
+            self.assertIn('has incorrect type', str(exc))
+            self.assertIn("response_json_paths in 'omega test'",
+                          str(exc))
+
     def test_response_headers(self):
         handler = core.HeadersResponseHandler()
         self.test.response = {'content-type': 'text/plain'}