I wasn't aware of LaunchpadWebServiceCaller, thanks for the heads-up! Actually, we _don't_ want to follow the redirect in test_user_access_to_private_bug_attachment, so the current behaviour of WebServiceCaller is just right :) Leonard, could you have a look at the incremental diff below? === modified file 'lib/lp/bugs/browser/tests/test_bugattachment_file_access.py' --- lib/lp/bugs/browser/tests/test_bugattachment_file_access.py 2011-01-05 09:39:00 +0000 +++ lib/lp/bugs/browser/tests/test_bugattachment_file_access.py 2011-01-06 11:40:15 +0000 @@ -25,6 +25,7 @@ from canonical.launchpad.interfaces.librarian import ( ILibraryFileAliasWithParent, ) +from canonical.launchpad.testing.pages import LaunchpadWebServiceCaller from canonical.launchpad.webapp.interfaces import ILaunchBag from canonical.launchpad.webapp.publisher import RedirectionView from canonical.launchpad.webapp.servers import LaunchpadTestRequest @@ -202,16 +203,19 @@ # Librarian URL. We cannot simply access these Librarian URLs # for restricted Librarian files because the host name used in # the URLs is different for each file, and our test envireonment - # does not support wildcard DNS. So let's disable the redirection - # mechanism in our client's HTTP connection and inspect the - # the Librarian URL. + # does not support wildcard DNS, and because the Launchpadlib + # browser automatically follows redirects. + # LaunchpadWebServiceCaller, on the other hand, gives us + # access to a raw HTTPResonse object. + webservice = LaunchpadWebServiceCaller( + 'launchpad-library', 'salgado-change-anything') + response = webservice.get(ws_bugattachment.data._wadl_resource._url) + self.assertEqual(303, response.status) + # The Librarian URL has, for our test case, the form # "https://NNNN.restricted.localhost:58000/NNNN/foo.txt?token=..." # where NNNN is an integer. - response, content = launchpad.rawGet( - ws_bugattachment.data._wadl_resource._url, follow_redirects=False) - self.assertEqual(303, response.status) - parsed_url = urlparse(response['location']) + parsed_url = urlparse(response.getHeader('location')) self.assertEqual('https', parsed_url.scheme) mo = re.search( r'^i\d+\.restricted\.localhost:58000$', parsed_url.netloc) @@ -222,7 +226,7 @@ self.assertEqual(['token'], params.keys()) # If a user which cannot access the private bug itself tries to - # to access the attachemnt, an Unauthorized error is raised. + # to access the attachment, an Unauthorized error is raised. other_launchpad = launchpadlib_for( 'test_unauthenticated', other_user, version='devel') self.assertRaises( === modified file 'lib/lp/testing/_webservice.py' --- lib/lp/testing/_webservice.py 2011-01-04 13:34:53 +0000 +++ lib/lp/testing/_webservice.py 2011-01-06 11:46:25 +0000 @@ -145,31 +145,7 @@ version = version or Launchpad.DEFAULT_VERSION cache = tempfile.mkdtemp(prefix='launchpadlib-cache-') zope.testing.cleanup.addCleanUp(_clean_up_cache, (cache,)) - return TestLaunchpad( - credentials, service_root, version=version, cache=cache) - - -class TestLaunchpad(Launchpad): - """A variant of the Launchpad service root class providing test helpers. - """ - - def rawGet(self, url, follow_redirects=None): - """Return a the result of a GET request for the given URL. - - :param url: The URL of the request. - :param follow_redirects: If None, keep the default behaviour. - If True, follow redirect responses. - If False, do not follow a redirect response but return the - plain redirect. - - :return: The tuple (response, content) - """ - default_redirect = self._browser._connection.follow_redirects - if follow_redirects is not None: - self._browser._connection.follow_redirects = follow_redirects - response, content = self._browser.get(url, return_response=True) - self._browser._connection.follow_redirects = default_redirect - return response, content + return Launchpad(credentials, service_root, version=version, cache=cache) class QueryCollector: What I don't like here is the usage of the "magic strings" 'launchpad-library', 'salgado-change-anything'. Is there a not-too-complicated way to setup the OAuth credentials for the owner of the test bug?