WebTest-2.0.18/0000755000000000000000000000000012560452473011665 5ustar rootrootWebTest-2.0.18/tests/0000755000000000000000000000000012560452473013027 5ustar rootrootWebTest-2.0.18/tests/html/0000755000000000000000000000000012560452473013773 5ustar rootrootWebTest-2.0.18/tests/html/form_inputs_with_defaults.html0000644000000000000000000000153312464666730022160 0ustar rootroot form page
WebTest-2.0.18/tests/html/form_unicode_inputs.html0000644000000000000000000000170312464666730020743 0ustar rootroot form page
WebTest-2.0.18/tests/html/app.js0000644000000000000000000000020512464666730015114 0ustar rootroot$(document).ready(function() { $('#myform').submit(function() { $('#message').text('Form submited'); return false; }); }); WebTest-2.0.18/tests/html/404.html0000644000000000000000000000026012464666730015174 0ustar rootroot
WebTest-2.0.18/tests/html/form_inputs.html0000644000000000000000000000425012464666730017235 0ustar rootroot forms page
WebTest-2.0.18/tests/html/message.html0000644000000000000000000000042612464666730016315 0ustar rootroot
%(message)s
WebTest-2.0.18/tests/html/index.html0000644000000000000000000000415112464666730015777 0ustar rootroot It Works!

It Works!

WebTest-2.0.18/tests/compat.py0000644000000000000000000000072412464666730014675 0ustar rootroot# -*- coding: utf-8 -*- try: # py < 2.7 import unittest2 as unittest except ImportError: import unittest # noqa try: unicode() except NameError: b = bytes def u(value): if isinstance(value, bytes): return value.decode('utf-8') return value else: def b(value): return str(value) def u(value): if isinstance(value, unicode): return value return unicode(value, 'utf-8') WebTest-2.0.18/tests/test_utils.py0000644000000000000000000000754712464666730015623 0ustar rootroot# -*- coding: utf-8 -*- from __future__ import unicode_literals import re import json from .compat import unittest from webtest import utils class NoDefaultTest(unittest.TestCase): def test_nodefault(self): from webtest.utils import NoDefault self.assertEquals(repr(NoDefault), '') class encode_paramsTest(unittest.TestCase): def test_encode_params_None(self): self.assertEquals(utils.encode_params(None, None), None) def test_encode_params_NoDefault(self): self.assertEquals(utils.encode_params(utils.NoDefault, None), '') def test_encode_params_dict_or_list(self): self.assertEquals(utils.encode_params({'foo': 'bar'}, None), utils.encode_params([('foo', 'bar')], None)) def test_encode_params_no_charset(self): # no content_type at all self.assertEquals(utils.encode_params({'foo': 'bar'}, None), 'foo=bar') # content_type without "charset=xxxx" self.assertEquals(utils.encode_params({'foo': 'bar'}, 'ba'), 'foo=bar') def test_encode_params_charset_utf8(self): # charset is using inconsistent casing on purpose, it should still work self.assertEquals(utils.encode_params({'f': '€'}, ' CHARset=uTF-8; '), 'f=%E2%82%AC') class make_patternTest(unittest.TestCase): def call_FUT(self, obj): from webtest.utils import make_pattern return make_pattern(obj) def test_make_pattern_None(self): self.assertEquals(self.call_FUT(None), None) def test_make_pattern_regex(self): regex = re.compile(r'foobar') self.assertEquals(self.call_FUT(regex), regex.search) def test_make_pattern_function(self): func = lambda x: x self.assertEquals(self.call_FUT(func), func) def test_make_pattern_bytes(self): # if we pass a string, it will get compiled into a regex # that we can later call and match a string self.assertEqual(self.call_FUT('a')('a').string, 'a') def test_make_pattern_invalid(self): self.assertRaises(ValueError, self.call_FUT, 0) class stringifyTest(unittest.TestCase): def test_stringify_text(self): self.assertEquals(utils.stringify("foo"), "foo") def test_stringify_binary(self): self.assertEquals(utils.stringify(b"foo"), "foo") def test_stringify_other(self): self.assertEquals(utils.stringify(123), "123") class json_methodTest(unittest.TestCase): class MockTestApp(object): """Mock TestApp used to test the json_object decorator.""" from webtest.utils import json_method JSONEncoder = json.JSONEncoder foo_json = json_method('FOO') def _gen_request(self, method, url, **kw): return (method, url, kw) mock = MockTestApp() def test_json_method_request_calls(self): from webtest.utils import NoDefault # no params self.assertEquals(self.mock.foo_json('url', params=NoDefault, c='c'), ('FOO', 'url', {'content_type': 'application/json', 'c': 'c', 'params': NoDefault, 'upload_files': None})) # params dumped to json self.assertEquals(self.mock.foo_json('url', params={'a': 'b'}, c='c'), ('FOO', 'url', {'content_type': 'application/json', 'c': 'c', 'params': json.dumps({'a': 'b'}), 'upload_files': None})) def test_json_method_doc(self): self.assertIn('FOO request', self.mock.foo_json.__doc__) self.assertIn('TestApp.foo', self.mock.foo_json.__doc__) def test_json_method_name(self): self.assertEqual(self.mock.foo_json.__name__, 'foo_json') WebTest-2.0.18/tests/test_response.py0000644000000000000000000003431312464666730016310 0ustar rootroot#coding: utf-8 from __future__ import unicode_literals import sys import webtest from webtest.debugapp import debug_app from webob import Request from webob.response import gzip_app_iter from webtest.compat import PY3 from tests.compat import unittest import webbrowser def links_app(environ, start_response): req = Request(environ) status = "200 OK" responses = { '/': """ page with links Foo Bar Baz Baz Baz Click me! Click me! """, '/foo/': ( 'This is foo. Bar ' '' ), '/foo/bar': 'This is foobar.', '/bar': 'This is bar.', '/baz/': 'This is baz.', '/spam/': 'This is spam.', '/egg/': 'Just eggs.', '/utf8/': """ Тестовая страница Менделеев Пушкин """, '/no_form/': """ Page without form

This is not the form you are looking for

""", '/one_forms/': """ Page without form
""", '/many_forms/': """ Page without form
""", '/html_in_anchor/': """ Page with HTML in an anchor tag Foo BarQuz """, '/json/': '{"foo": "bar"}', } utf8_paths = ['/utf8/'] body = responses[req.path_info] body = body.encode('utf8') headers = [ ('Content-Type', str('text/html')), ('Content-Length', str(len(body))) ] if req.path_info in utf8_paths: headers[0] = ('Content-Type', str('text/html; charset=utf-8')) start_response(str(status), headers) return [body] def gzipped_app(environ, start_response): status = "200 OK" encoded_body = list(gzip_app_iter([b'test'])) headers = [ ('Content-Type', str('text/html')), ('Content-Encoding', str('gzip')), ] start_response(str(status), headers) return encoded_body class TestResponse(unittest.TestCase): def test_repr(self): def _repr(v): br = repr(v) if len(br) > 18: br = br[:10] + '...' + br[-5:] br += '/%s' % len(v) return br app = webtest.TestApp(debug_app) res = app.post('/') self.assertEqual( repr(res), '<200 OK text/plain body=%s>' % _repr(res.body) ) res.content_type = None self.assertEqual( repr(res), '<200 OK body=%s>' % _repr(res.body) ) res.location = 'http://pylons.org' self.assertEqual( repr(res), '<200 OK location: http://pylons.org body=%s>' % _repr(res.body) ) res.body = b'' self.assertEqual( repr(res), '<200 OK location: http://pylons.org no body>' ) def test_mustcontains(self): app = webtest.TestApp(debug_app) res = app.post('/', params='foobar') res.mustcontain('foobar') self.assertRaises(IndexError, res.mustcontain, 'not found') res.mustcontain('foobar', no='not found') res.mustcontain('foobar', no=['not found', 'not found either']) self.assertRaises(IndexError, res.mustcontain, no='foobar') self.assertRaises( TypeError, res.mustcontain, invalid_param='foobar' ) def test_click(self): app = webtest.TestApp(links_app) self.assertIn('This is foo.', app.get('/').click('Foo')) self.assertIn( 'This is foobar.', app.get('/').click('Foo').click('Bar') ) self.assertIn('This is bar.', app.get('/').click('Bar')) # should skip non-clickable links self.assertIn( 'This is baz.', app.get('/').click('Baz') ) self.assertIn('This is baz.', app.get('/').click(linkid='id_baz')) self.assertIn('This is baz.', app.get('/').click(href='baz/')) self.assertIn( 'This is spam.', app.get('/').click('Click me!', index=0) ) self.assertIn( 'Just eggs.', app.get('/').click('Click me!', index=1) ) self.assertIn( 'This is foo.', app.get('/html_in_anchor/').click('baz qux') ) def dont_match_anchor_tag(): app.get('/html_in_anchor/').click('href') self.assertRaises(IndexError, dont_match_anchor_tag) def multiple_links(): app.get('/').click('Click me!') self.assertRaises(IndexError, multiple_links) def invalid_index(): app.get('/').click('Click me!', index=2) self.assertRaises(IndexError, invalid_index) def no_links_found(): app.get('/').click('Ham') self.assertRaises(IndexError, no_links_found) def tag_inside_script(): app.get('/').click('Boo') self.assertRaises(IndexError, tag_inside_script) def test_click_utf8(self): app = webtest.TestApp(links_app, use_unicode=False) resp = app.get('/utf8/') self.assertEqual(resp.charset, 'utf-8') if not PY3: # No need to deal with that in Py3 self.assertIn("Тестовая страница".encode('utf8'), resp) self.assertIn("Тестовая страница", resp, resp) target = 'Менделеев'.encode('utf8') self.assertIn('This is foo.', resp.click(target, verbose=True)) def test_click_u(self): app = webtest.TestApp(links_app) resp = app.get('/utf8/') self.assertIn("Тестовая страница", resp) self.assertIn('This is foo.', resp.click('Менделеев')) def test_clickbutton(self): app = webtest.TestApp(links_app) self.assertIn( 'This is foo.', app.get('/').clickbutton(buttonid='button1', verbose=True) ) self.assertRaises( IndexError, app.get('/').clickbutton, buttonid='button2' ) self.assertRaises( IndexError, app.get('/').clickbutton, buttonid='button3' ) def test_xml_attribute(self): app = webtest.TestApp(links_app) resp = app.get('/no_form/') self.assertRaises( AttributeError, getattr, resp, 'xml' ) resp.content_type = 'text/xml' resp.xml @unittest.skipIf('PyPy' in sys.version, 'skip lxml tests on pypy') def test_lxml_attribute(self): app = webtest.TestApp(links_app) resp = app.post('/') resp.content_type = 'text/xml' print(resp.body) print(resp.lxml) def test_html_attribute(self): app = webtest.TestApp(links_app) res = app.post('/') res.content_type = 'text/plain' self.assertRaises( AttributeError, getattr, res, 'html' ) def test_no_form(self): app = webtest.TestApp(links_app) resp = app.get('/no_form/') self.assertRaises( TypeError, getattr, resp, 'form' ) def test_one_forms(self): app = webtest.TestApp(links_app) resp = app.get('/one_forms/') self.assertEqual(resp.form.id, 'first_form') def test_too_many_forms(self): app = webtest.TestApp(links_app) resp = app.get('/many_forms/') self.assertRaises( TypeError, getattr, resp, 'form' ) def test_showbrowser(self): def open_new(f): self.filename = f webbrowser.open_new = open_new app = webtest.TestApp(debug_app) res = app.post('/') res.showbrowser() def test_unicode_normal_body(self): app = webtest.TestApp(debug_app) res = app.post('/') self.assertRaises( AttributeError, getattr, res, 'unicode_normal_body' ) res.charset = 'latin1' res.body = 'été'.encode('latin1') self.assertEqual(res.unicode_normal_body, 'été') def test_testbody(self): app = webtest.TestApp(debug_app) res = app.post('/') res.charset = 'utf8' res.body = 'été'.encode('latin1') res.testbody def test_xml(self): app = webtest.TestApp(links_app) resp = app.get('/no_form/') self.assertRaises( AttributeError, getattr, resp, 'xml' ) resp.content_type = 'text/xml' resp.xml def test_json(self): app = webtest.TestApp(links_app) resp = app.get('/json/') with self.assertRaises(AttributeError): resp.json resp.content_type = 'text/json' self.assertIn('foo', resp.json) resp.content_type = 'application/json' self.assertIn('foo', resp.json) resp.content_type = 'application/vnd.webtest+json' self.assertIn('foo', resp.json) def test_unicode(self): app = webtest.TestApp(links_app) resp = app.get('/') if not PY3: unicode(resp) print(resp.__unicode__()) def test_content_dezips(self): app = webtest.TestApp(gzipped_app) resp = app.get('/') self.assertEqual(resp.body, b'test') class TestFollow(unittest.TestCase): def get_redirects_app(self, count=1, locations=None): """Return an app that issues a redirect ``count`` times""" remaining_redirects = [count] # this means "nonlocal" if locations is None: locations = ['/'] * count def app(environ, start_response): headers = [('Content-Type', str('text/html'))] if remaining_redirects[0] == 0: status = "200 OK" body = b"done" else: status = "302 Found" body = b'' nextloc = str(locations.pop(0)) headers.append(('location', nextloc)) remaining_redirects[0] -= 1 headers.append(('Content-Length', str(len(body)))) start_response(str(status), headers) return [body] return webtest.TestApp(app) def test_follow_with_cookie(self): app = webtest.TestApp(debug_app) app.get('/?header-set-cookie=foo=bar') self.assertEqual(app.cookies['foo'], 'bar') resp = app.get('/?status=302%20Found&header-location=/') resp = resp.follow() resp.mustcontain('HTTP_COOKIE: foo=bar') def test_follow(self): app = self.get_redirects_app(1) resp = app.get('/') self.assertEqual(resp.status_int, 302) resp = resp.follow() self.assertEqual(resp.body, b'done') # can't follow non-redirect self.assertRaises(AssertionError, resp.follow) def test_follow_relative(self): app = self.get_redirects_app(2, ['hello/foo/', 'bar']) resp = app.get('/') self.assertEqual(resp.status_int, 302) resp = resp.follow() self.assertEqual(resp.status_int, 302) resp = resp.follow() self.assertEqual(resp.body, b'done') self.assertEqual(resp.request.url, 'http://localhost/hello/foo/bar') def test_follow_twice(self): app = self.get_redirects_app(2) resp = app.get('/').follow() self.assertEqual(resp.status_int, 302) resp = resp.follow() self.assertEqual(resp.status_int, 200) def test_maybe_follow_200(self): app = self.get_redirects_app(0) resp = app.get('/').maybe_follow() self.assertEqual(resp.body, b'done') def test_maybe_follow_once(self): app = self.get_redirects_app(1) resp = app.get('/').maybe_follow() self.assertEqual(resp.body, b'done') def test_maybe_follow_twice(self): app = self.get_redirects_app(2) resp = app.get('/').maybe_follow() self.assertEqual(resp.body, b'done') def test_maybe_follow_infinite(self): app = self.get_redirects_app(100000) self.assertRaises(AssertionError, app.get('/').maybe_follow) WebTest-2.0.18/tests/deploy.ini0000644000000000000000000000012412464666730015027 0ustar rootroot[app:main] paste.app_factory = webtest.debugapp:make_debug_app form =
WebTest-2.0.18/tests/test_lint.py0000644000000000000000000002404012464666730015414 0ustar rootroot# -*- coding: utf-8 -*- from __future__ import unicode_literals from six import PY3 from six import StringIO from tests.compat import unittest from webob import Request, Response import warnings import mock from webtest import TestApp from webtest.compat import to_bytes from webtest.lint import check_headers from webtest.lint import check_content_type from webtest.lint import check_environ from webtest.lint import IteratorWrapper from webtest.lint import WriteWrapper from webtest.lint import ErrorWrapper from webtest.lint import InputWrapper from webtest.lint import to_string from webtest.lint import middleware from six import BytesIO def application(environ, start_response): req = Request(environ) resp = Response() env_input = environ['wsgi.input'] len_body = len(req.body) env_input.input.seek(0) if req.path_info == '/read': resp.body = env_input.read(len_body) elif req.path_info == '/read_line': resp.body = env_input.readline(len_body) elif req.path_info == '/read_lines': resp.body = b'-'.join(env_input.readlines(len_body)) elif req.path_info == '/close': resp.body = env_input.close() return resp(environ, start_response) class TestToString(unittest.TestCase): def test_to_string(self): self.assertEqual(to_string('foo'), 'foo') self.assertEqual(to_string(b'foo'), 'foo') class TestMiddleware(unittest.TestCase): def test_lint_too_few_args(self): linter = middleware(application) with self.assertRaisesRegexp(AssertionError, "Two arguments required"): linter() with self.assertRaisesRegexp(AssertionError, "Two arguments required"): linter({}) def test_lint_no_keyword_args(self): linter = middleware(application) with self.assertRaisesRegexp(AssertionError, "No keyword arguments " "allowed"): linter({}, 'foo', baz='baz') #TODO: test start_response_wrapper @mock.patch.multiple('webtest.lint', check_environ=lambda x: True, # don't block too early InputWrapper=lambda x: True) def test_lint_iterator_returned(self): linter = middleware(lambda x, y: None) # None is not an iterator msg = "The application must return an iterator, if only an empty list" with self.assertRaisesRegexp(AssertionError, msg): linter({'wsgi.input': 'foo', 'wsgi.errors': 'foo'}, 'foo') class TestInputWrapper(unittest.TestCase): def test_read(self): app = TestApp(application) resp = app.post('/read', 'hello') self.assertEqual(resp.body, b'hello') def test_readline(self): app = TestApp(application) resp = app.post('/read_line', 'hello\n') self.assertEqual(resp.body, b'hello\n') def test_readlines(self): app = TestApp(application) resp = app.post('/read_lines', 'hello\nt\n') self.assertEqual(resp.body, b'hello\n-t\n') def test_close(self): input_wrapper = InputWrapper(None) self.assertRaises(AssertionError, input_wrapper.close) def test_iter(self): data = to_bytes("A line\nAnother line\nA final line\n") input_wrapper = InputWrapper(BytesIO(data)) self.assertEquals(to_bytes("").join(input_wrapper), data, '') def test_seek(self): data = to_bytes("A line\nAnother line\nA final line\n") input_wrapper = InputWrapper(BytesIO(data)) input_wrapper.seek(0) self.assertEquals(to_bytes("").join(input_wrapper), data, '') class TestMiddleware2(unittest.TestCase): def test_exc_info(self): def application_exc_info(environ, start_response): body = to_bytes('body stuff') headers = [ ('Content-Type', 'text/plain; charset=utf-8'), ('Content-Length', str(len(body)))] start_response(to_bytes('200 OK'), headers, ('stuff',)) return [body] app = TestApp(application_exc_info) app.get('/') # don't know what to assert here... a bit cheating, just covers code class TestCheckContentType(unittest.TestCase): def test_no_content(self): status = "204 No Content" headers = [ ('Content-Type', 'text/plain; charset=utf-8'), ('Content-Length', '4') ] self.assertRaises(AssertionError, check_content_type, status, headers) def test_no_content_type(self): status = "200 OK" headers = [ ('Content-Length', '4') ] self.assertRaises(AssertionError, check_content_type, status, headers) class TestCheckHeaders(unittest.TestCase): @unittest.skipIf(not PY3, 'Useless in Python2') def test_header_unicode_value(self): self.assertRaises(AssertionError, check_headers, [('X-Price', '100€')]) @unittest.skipIf(not PY3, 'Useless in Python2') def test_header_unicode_name(self): self.assertRaises(AssertionError, check_headers, [('X-€', 'foo')]) class TestCheckEnviron(unittest.TestCase): def test_no_query_string(self): environ = { 'REQUEST_METHOD': str('GET'), 'SERVER_NAME': str('localhost'), 'SERVER_PORT': str('80'), 'wsgi.version': (1, 0, 1), 'wsgi.input': StringIO('test'), 'wsgi.errors': StringIO(), 'wsgi.multithread': None, 'wsgi.multiprocess': None, 'wsgi.run_once': None, 'wsgi.url_scheme': 'http', 'PATH_INFO': str('/'), } with warnings.catch_warnings(record=True) as w: warnings.simplefilter("always") check_environ(environ) self.assertEqual(len(w), 1, "We should have only one warning") self.assertTrue( "QUERY_STRING" in str(w[-1].message), "The warning message should say something about QUERY_STRING") def test_no_valid_request(self): environ = { 'REQUEST_METHOD': str('PROPFIND'), 'SERVER_NAME': str('localhost'), 'SERVER_PORT': str('80'), 'wsgi.version': (1, 0, 1), 'wsgi.input': StringIO('test'), 'wsgi.errors': StringIO(), 'wsgi.multithread': None, 'wsgi.multiprocess': None, 'wsgi.run_once': None, 'wsgi.url_scheme': 'http', 'PATH_INFO': str('/'), 'QUERY_STRING': str(''), } with warnings.catch_warnings(record=True) as w: warnings.simplefilter("always") check_environ(environ) self.assertEqual(len(w), 1, "We should have only one warning") self.assertTrue( "REQUEST_METHOD" in str(w[-1].message), "The warning message should say something " "about REQUEST_METHOD") def test_handles_native_strings_in_variables(self): # "native string" means unicode in py3, but bytes in py2 path = '/umläut' if not PY3: path = path.encode('utf-8') environ = { 'REQUEST_METHOD': str('GET'), 'SERVER_NAME': str('localhost'), 'SERVER_PORT': str('80'), 'wsgi.version': (1, 0, 1), 'wsgi.input': StringIO('test'), 'wsgi.errors': StringIO(), 'wsgi.multithread': None, 'wsgi.multiprocess': None, 'wsgi.run_once': None, 'wsgi.url_scheme': 'http', 'PATH_INFO': path, 'QUERY_STRING': str(''), } with warnings.catch_warnings(record=True) as w: warnings.simplefilter("always") check_environ(environ) self.assertEqual(0, len(w), "We should have no warning") class TestIteratorWrapper(unittest.TestCase): def test_close(self): class MockIterator(object): def __init__(self): self.closed = False def __iter__(self): return self def __next__(self): return None next = __next__ def close(self): self.closed = True mock = MockIterator() wrapper = IteratorWrapper(mock, None) wrapper.close() self.assertTrue(mock.closed, "Original iterator has not been closed") class TestWriteWrapper(unittest.TestCase): def test_wrong_type(self): write_wrapper = WriteWrapper(None) self.assertRaises(AssertionError, write_wrapper, 'not a binary') def test_normal(self): class MockWriter(object): def __init__(self): self.written = [] def __call__(self, s): self.written.append(s) data = to_bytes('foo') mock = MockWriter() write_wrapper = WriteWrapper(mock) write_wrapper(data) self.assertEqual( mock.written, [data], "WriterWrapper should call original writer when data is binary " "type") class TestErrorWrapper(unittest.TestCase): def test_dont_close(self): error_wrapper = ErrorWrapper(None) self.assertRaises(AssertionError, error_wrapper.close) class FakeError(object): def __init__(self): self.written = [] self.flushed = False def write(self, s): self.written.append(s) def writelines(self, lines): for line in lines: self.write(line) def flush(self): self.flushed = True def test_writelines(self): fake_error = self.FakeError() error_wrapper = ErrorWrapper(fake_error) data = [to_bytes('a line'), to_bytes('another line')] error_wrapper.writelines(data) self.assertEqual(fake_error.written, data, "ErrorWrapper should call original writer") def test_flush(self): fake_error = self.FakeError() error_wrapper = ErrorWrapper(fake_error) error_wrapper.flush() self.assertTrue( fake_error.flushed, "ErrorWrapper should have called original wsgi_errors's flush") WebTest-2.0.18/tests/test_ext.py0000644000000000000000000000033712464666730015251 0ustar rootroot# -*- coding: utf-8 -*- # -*- coding: utf-8 -*- from .compat import unittest from webtest import ext class TestSelenium(unittest.TestCase): def test_raises(self): self.assertRaises(ImportError, ext.casperjs) WebTest-2.0.18/tests/test_http.py0000644000000000000000000000414412464666730015430 0ustar rootroot# -*- coding: utf-8 -*- from tests.compat import unittest from webob import Request from webtest.debugapp import debug_app from webtest import http class TestServer(unittest.TestCase): def setUp(self): self.s = http.StopableWSGIServer.create(debug_app) def test_server(self): s = self.s s.wait() self.assertEqual(200, http.check_server(s.adj.host, s.adj.port, '/__application__')) self.assertEqual(200, http.check_server(s.adj.host, s.adj.port, '/__file__?__file__=' + __file__)) self.assertEqual(404, http.check_server(s.adj.host, s.adj.port, '/__file__?__file__=XXX')) self.assertEqual(304, http.check_server(s.adj.host, s.adj.port, '/?status=304')) def test_wsgi_wrapper(self): s = self.s s.wait() req = Request.blank('/__application__') resp = req.get_response(s.wrapper) self.assertEqual(resp.status_int, 200) req = Request.blank('/__file__?__file__=' + __file__) resp = req.get_response(s.wrapper) self.assertEqual(resp.status_int, 200) req = Request.blank('/__file__?__file__=XXX') resp = req.get_response(s.wrapper) self.assertEqual(resp.status_int, 404) req = Request.blank('/?status=304') resp = req.get_response(s.wrapper) self.assertEqual(resp.status_int, 304) def tearDown(self): self.s.shutdown() class TestBrokenServer(unittest.TestCase): def test_shutdown_non_running(self): host, port = http.get_free_port() s = http.StopableWSGIServer(debug_app, host=host, port=port) self.assertFalse(s.wait(retries=-1)) self.assertTrue(s.shutdown()) class TestClient(unittest.TestCase): def test_no_server(self): host, port = http.get_free_port() self.assertEqual(0, http.check_server(host, port, retries=2)) WebTest-2.0.18/tests/test_sel.py0000644000000000000000000000037712464666730015240 0ustar rootroot# -*- coding: utf-8 -*- from .compat import unittest from webtest import sel class TestSelenium(unittest.TestCase): def test_raises(self): self.assertRaises(ImportError, sel.SeleniumApp) self.assertRaises(ImportError, sel.selenium) WebTest-2.0.18/tests/__init__.py0000644000000000000000000000000212464666730015136 0ustar rootroot# WebTest-2.0.18/tests/test_debugapp.py0000644000000000000000000001424512464666730016243 0ustar rootroot# -*- coding: utf-8 -*- from __future__ import unicode_literals import os import sys import six import webtest from webtest.debugapp import debug_app from webtest.compat import PY3 from webtest.compat import to_bytes from webtest.compat import print_stderr from webtest.app import AppError from tests.compat import unittest import webbrowser def test_print_unicode(): print_stderr('°C') class TestTesting(unittest.TestCase): def setUp(self): self.app = webtest.TestApp(debug_app) def test_url_class(self): class U: def __str__(self): return '/' res = self.app.get(U()) self.assertEqual(res.status_int, 200) def test_testing(self): res = self.app.get('/') self.assertEqual(res.status_int, 200) self.assertEqual(res.headers['content-type'], 'text/plain') self.assertEqual(res.content_type, 'text/plain') res = self.app.request('/', method='GET') self.assertEqual(res.status_int, 200) self.assertEqual(res.headers['content-type'], 'text/plain') self.assertEqual(res.content_type, 'text/plain') res = self.app.head('/') self.assertEqual(res.status_int, 200) self.assertEqual(res.headers['content-type'], 'text/plain') self.assertTrue(res.content_length > 0) self.assertEqual(res.body, to_bytes('')) res = self.app.head('/', xhr=True) self.assertEqual(res.status_int, 200) def test_post_unicode(self): res = self.app.post( '/', params=dict(a='é'), content_type='application/x-www-form-urlencoded;charset=utf8') res.mustcontain('a=%C3%A9') def test_post_unicode_body(self): res = self.app.post( '/', params='é', content_type='text/plain; charset=utf8') self.assertTrue(res.body.endswith(b'\xc3\xa9')) res.mustcontain('é') def test_post_params(self): res = self.app.post('/', params=dict(a=1)) res.mustcontain('a=1') res = self.app.post('/', params=[('a', '1')]) res.mustcontain('a=1') res = self.app.post_json('/', params=dict(a=1)) res.mustcontain('{"a": 1}') res = self.app.post_json('/', params=False) res.mustcontain('false') def test_put_params(self): res = self.app.put('/', params=dict(a=1)) res.mustcontain('a=1') res = self.app.put_json('/', params=dict(a=1)) res.mustcontain('{"a": 1}') res = self.app.put_json('/', params=False) res.mustcontain('false') def test_delete_params(self): res = self.app.delete('/', params=dict(a=1)) res.mustcontain('a=1') res = self.app.delete_json('/', params=dict(a=1)) res.mustcontain('{"a": 1}') def test_options(self): res = self.app.options('/') self.assertEqual(res.status_int, 200) def test_exception(self): self.assertRaises(Exception, self.app.get, '/?error=t') self.assertRaises(webtest.AppError, self.app.get, '/?status=404%20Not%20Found') def test_bad_content_type(self): resp = self.app.get('/') self.assertRaises(AttributeError, lambda: resp.json) resp = self.app.get('/?header-content-type=application/json') self.assertRaises(AttributeError, lambda: resp.pyquery) self.assertRaises(AttributeError, lambda: resp.lxml) self.assertRaises(AttributeError, lambda: resp.xml) def test_app_from_config_file(self): config = os.path.join(os.path.dirname(__file__), 'deploy.ini') app = webtest.TestApp('config:%s#main' % config) resp = app.get('/') self.assertEqual(resp.status_int, 200) def test_errors(self): try: self.app.get('/?errorlog=somelogs') assert(False, "An AppError should be raised") except AppError: e = sys.exc_info()[1] assert six.text_type(e) \ == "Application had errors logged:\nsomelogs" def test_request_obj(self): res = self.app.get('/') res = self.app.request(res.request) def test_showbrowser(self): open_new = webbrowser.open_new self.filename = '' def open_new(f): self.filename = f webbrowser.open_new = open_new res = self.app.get('/') res.showbrowser() assert self.filename.startswith('file://'), self.filename def test_303(self): res = self.app.get('/?status=302%20Redirect&header-location=/foo') self.assertEqual(res.status_int, 302) print(res.location) self.assertEqual(res.location, 'http://localhost/foo', res) self.assertEqual(res.headers['location'], 'http://localhost/foo') res = res.follow() self.assertEqual(res.request.url, 'http://localhost/foo') self.assertIn('Response: 200 OK', str(res)) self.assertIn('200 OK', repr(res)) self.app.get('/?status=303%20redirect', status='3*') def test_204(self): self.app.post('/?status=204%20OK') def test_404(self): self.app.get('/?status=404%20Not%20Found', status=404) self.assertRaises(webtest.AppError, self.app.get, '/', status=404) def test_print_stderr(self): res = self.app.get('/') res.charset = 'utf-8' res.text = '°C' print_stderr(str(res)) res.charset = None print_stderr(str(res)) def test_app_error(self): res = self.app.get('/') res.charset = 'utf-8' res.text = '°C' AppError('%s %s %s %s', res.status, '', res.request.url, res) res.charset = None AppError('%s %s %s %s', res.status, '', res.request.url, res) def test_exception_repr(self): res = self.app.get('/') res.charset = 'utf-8' res.text = '°C' if not PY3: unicode(AssertionError(res)) str(AssertionError(res)) res.charset = None if not PY3: unicode(AssertionError(res)) str(AssertionError(res)) def test_fake_dict(self): class FakeDict(object): def items(self): return [('a', '10'), ('a', '20')] self.app.post('/params', params=FakeDict()) WebTest-2.0.18/tests/test_forms.py0000644000000000000000000011070412464666730015577 0ustar rootroot# -*- coding: utf-8 -*- from __future__ import unicode_literals import os.path import struct import sys import webtest import six from six import binary_type from six import PY3 from webob import Request from webtest.debugapp import DebugApp from webtest.compat import to_bytes from webtest.forms import NoValue, Submit, Upload from tests.compat import unittest from tests.compat import u class TestForms(unittest.TestCase): def callFUT(self, filename='form_inputs.html', formid='simple_form'): dirname = os.path.join(os.path.dirname(__file__), 'html') app = DebugApp(form=os.path.join(dirname, filename), show_form=True) resp = webtest.TestApp(app).get('/form.html') return resp.forms[formid] def test_set_submit_field(self): form = self.callFUT() self.assertRaises( AttributeError, form['submit'].value__set, 'foo' ) def test_button(self): form = self.callFUT() button = form['button'] self.assertTrue(isinstance(button, Submit), " """ def get_submit_app(form_id, form_fields_text): def submit_app(environ, start_response): req = Request(environ) status = "200 OK" if req.method == "GET": body = """ form page
%s
""" % (form_id, form_fields_text) else: body_head = """ display page """ body_parts = [] for (name, value) in req.POST.items(): if hasattr(value, 'filename'): body_parts.append("%s:%s:%s\n" % ( name, value.filename, value.value.decode('ascii'))) else: body_parts.append("%s:%s\n" % ( name, value)) body_foot = """ """ body = body_head + "".join(body_parts) + body_foot if not isinstance(body, binary_type): body = body.encode('utf8') headers = [ ('Content-Type', 'text/html; charset=utf-8'), ('Content-Length', str(len(body)))] start_response(status, headers) return [body] return submit_app class TestFieldOrder(unittest.TestCase): def test_submit_with_file_upload(self): uploaded_file_name = 'test.txt' uploaded_file_contents = 'test content file upload' if PY3: uploaded_file_contents = to_bytes(uploaded_file_contents) deform_upload_file_app = get_submit_app('deform', deform_upload_fields_text) app = webtest.TestApp(deform_upload_file_app) res = app.get('/') self.assertEqual(res.status_int, 200) self.assertEqual( res.headers['content-type'], 'text/html; charset=utf-8') self.assertEqual(res.content_type, 'text/html') self.assertEqual(res.charset, 'utf-8') single_form = res.forms["deform"] single_form.set("title", "testtitle") single_form.set("fileupload", (uploaded_file_name, uploaded_file_contents)) single_form.set("description", "testdescription") display = single_form.submit("Submit") self.assertIn(""" _charset_: __formid__:deform title:testtitle __start__:fileupload:mapping fileupload:test.txt:test content file upload __end__:fileupload:mapping description:testdescription Submit:Submit """.strip(), display, display) def test_post_with_file_upload(self): uploaded_file_name = 'test.txt' uploaded_file_contents = 'test content file upload' if PY3: uploaded_file_contents = to_bytes(uploaded_file_contents) deform_upload_file_app = get_submit_app('deform', deform_upload_fields_text) app = webtest.TestApp(deform_upload_file_app) display = app.post("/", OrderedDict([ ('_charset_', ''), ('__formid__', 'deform'), ('title', 'testtitle'), ('__start__', 'fileupload:mapping'), ('fileupload', webtest.Upload(uploaded_file_name, uploaded_file_contents)), ('__end__', 'fileupload:mapping'), ('description', 'testdescription'), ('Submit', 'Submit')])) self.assertIn(""" _charset_: __formid__:deform title:testtitle __start__:fileupload:mapping fileupload:test.txt:test content file upload __end__:fileupload:mapping description:testdescription Submit:Submit""".strip(), display, display) def test_field_order_is_across_all_fields(self): fields = """ """ submit_app = get_submit_app('test', fields) app = webtest.TestApp(submit_app) get_res = app.get("/") # Submit the form with the second submit button. display = get_res.forms[0].submit('save', 1) self.assertIn(""" letter:a letter:b number:1 letter:c number:2 letter:d save:Save 2 letter:e""".strip(), display, display) class TestFragments(unittest.TestCase): def test_url_without_fragments(self): app = webtest.TestApp(debug_app) res = app.get('http://localhost/') self.assertEqual(res.status_int, 200) def test_url_with_fragments(self): app = webtest.TestApp(debug_app) res = app.get('http://localhost/#ananchor') self.assertEqual(res.status_int, 200) def application(environ, start_response): req = Request(environ) if req.path_info == '/redirect': req.path_info = '/path' resp = Response() resp.status = '302 Found' resp.location = req.path else: resp = Response() resp.body = to_bytes( 'link' % req.path) return resp(environ, start_response) class TestScriptName(unittest.TestCase): def test_script_name(self): app = webtest.TestApp(application) resp = app.get('/script', extra_environ={'SCRIPT_NAME': '/script'}) resp.mustcontain('href="/script"') resp = app.get('/script/redirect', extra_environ={'SCRIPT_NAME': '/script'}) self.assertEqual(resp.status_int, 302) self.assertEqual(resp.location, 'http://localhost/script/path', resp.location) resp = resp.follow(extra_environ={'SCRIPT_NAME': '/script'}) resp.mustcontain('href="/script/path"') resp = resp.click('link') resp.mustcontain('href="/script/path"') def test_app_script_name(self): app = webtest.TestApp(application, extra_environ={'SCRIPT_NAME': '/script'}) resp = app.get('/script/redirect') self.assertEqual(resp.status_int, 302) self.assertEqual(resp.location, 'http://localhost/script/path', resp.location) resp = resp.follow() resp.mustcontain('href="/script/path"') resp = resp.click('link') resp.mustcontain('href="/script/path"') def test_script_name_doesnt_match(self): app = webtest.TestApp(application) resp = app.get('/path', extra_environ={'SCRIPT_NAME': '/script'}) resp.mustcontain('href="/script/path"') class TestWSGIProxy(unittest.TestCase): def setUp(self): self.s = http.StopableWSGIServer.create(debug_app) self.s.wait() def test_proxy_with_url(self): app = webtest.TestApp(self.s.application_url) resp = app.get('/') self.assertEqual(resp.status_int, 200) def test_proxy_with_environ(self): def app(environ, start_response): pass os.environ['WEBTEST_TARGET_URL'] = self.s.application_url app = webtest.TestApp(app) del os.environ['WEBTEST_TARGET_URL'] resp = app.get('/') self.assertEqual(resp.status_int, 200) def tearDown(self): self.s.shutdown() class TestAppXhrParam(unittest.TestCase): def setUp(self): self.app = webtest.TestApp(debug_app) def test_xhr_param_change_headers(self): app = self.app # FIXME: this test isn`t work for head request # now I don't know how to test head request functions = (app.get, app.post, app.delete, app.put, app.options) # app.head for func in functions: resp = func('/', xhr=True) resp.charset = 'ascii' self.assertIn('HTTP_X_REQUESTED_WITH: XMLHttpRequest', resp.text) WebTest-2.0.18/tests/test_authorisation.py0000644000000000000000000000266712464666730017352 0ustar rootroot# -*- coding: utf-8 -*- from __future__ import unicode_literals from webtest.debugapp import DebugApp from tests.compat import unittest from base64 import b64decode from webtest.compat import to_bytes import webtest class TestAuthorization(unittest.TestCase): def callFUT(self): return webtest.TestApp(DebugApp()) def test_basic_authorization(self): app = self.callFUT() authorization = ('Basic', ['gawel', 'passwd']) app.authorization = authorization self.assertIn('HTTP_AUTHORIZATION', app.extra_environ) self.assertEquals(app.authorization, authorization) resp = app.get('/') resp.mustcontain('HTTP_AUTHORIZATION: Basic Z2F3ZWw6cGFzc3dk') header = resp.request.environ['HTTP_AUTHORIZATION'] self.assertTrue(header.startswith('Basic ')) authtype, value = header.split(' ') auth = (authtype, b64decode(to_bytes(value)).decode('latin1').split(':')) self.assertEquals(authorization, auth) app.authorization = None self.assertNotIn('HTTP_AUTHORIZATION', app.extra_environ) def test_invalid(self): app = self.callFUT() self.assertRaises(ValueError, app.set_authorization, ()) self.assertRaises(ValueError, app.set_authorization, '') self.assertRaises(ValueError, app.set_authorization, ('Basic', '')) self.assertRaises(ValueError, app.set_authorization, ('Basic', ())) WebTest-2.0.18/docs/0000755000000000000000000000000012560452473012615 5ustar rootrootWebTest-2.0.18/docs/index.rst0000644000000000000000000000730512464666730014471 0ustar rootroot================================= Testing Applications with WebTest ================================= :author: Ian Bicking :maintainer: Gael Pasgrimaud Status & License ================ WebTest is an extraction of ``paste.fixture.TestApp``, rewriting portions to use `WebOb `_. It is under active development as part of the Pylons cloud of packages. Feedback and discussion should take place on the `Pylons discuss list `_, and bugs should go into the `Github tracker `_. This library is licensed under an `MIT-style license `_. Installation ============ You can use pip or easy_install to get the latest stable release: .. code-block:: sh $ pip install WebTest $ easy_install WebTest Or if you want the development version: .. code-block:: sh $ pip install https://nodeload.github.com/Pylons/webtest/tar.gz/master What This Does ============== WebTest helps you test your WSGI-based web applications. This can be any application that has a WSGI interface, including an application written in a framework that supports WSGI (which includes most actively developed Python web frameworks -- almost anything that even nominally supports WSGI should be testable). With this you can test your web applications without starting an HTTP server, and without poking into the web framework shortcutting pieces of your application that need to be tested. The tests WebTest runs are entirely equivalent to how a WSGI HTTP server would call an application. By testing the full stack of your application, the WebTest testing model is sometimes called a *functional test*, *integration test*, or *acceptance test* (though the latter two are not particularly good descriptions). This is in contrast to a *unit test* which tests a particular piece of functionality in your application. While complex programming tasks are often suited to unit tests, template logic and simple web programming is often best done with functional tests; and regardless of the presence of unit tests, no testing strategy is complete without high-level tests to ensure the entire programming system works together. WebTest helps you create tests by providing a convenient interface to run WSGI applications and verify the output. Quick start =========== The most important object in WebTest is :class:`~webtest.TestApp`, the wrapper for WSGI applications. It also allows you to perform HTTP requests on it. To use it, you simply instantiate it with your WSGI application. .. note:: If your WSGI application requires any configuration, you must set that up manually in your tests. Here is a basic application:: >>> def application(environ, start_response): ... headers = [('Content-Type', 'text/html; charset=utf8'), ... ('Content-Length', str(len(body)))] ... start_response('200 OK', headers) ... return [body] Wrap it into a :class:`~webtest.TestApp`:: >>> from webtest import TestApp >>> app = TestApp(application) Then you can get the response of a HTTP GET:: >>> resp = app.get('/') And check the results, like response's status:: >>> assert resp.status == '200 OK' >>> assert resp.status_int == 200 Response's headers:: >>> assert resp.content_type == 'text/html' >>> assert resp.content_length > 0 Or response's body:: >>> resp.mustcontain('') >>> assert 'form' in resp WebTest can do much more. In particular, it can handle :doc:`forms` and :doc:`json`. Contents ======== .. toctree:: webtest.rst api.rst contributing.rst changelog.rst .. include:: license.rst WebTest-2.0.18/docs/webtest.rst0000644000000000000000000000205612464666730015035 0ustar rootroot====================================== Functional Testing of Web Applications ====================================== .. toctree:: testapp.rst testresponse.rst http.rst debugapp.rst Framework Hooks =============== Frameworks can detect that they are in a testing environment by the presence (and truth) of the WSGI environmental variable ``"paste.testing"`` (the key name is inherited from ``paste.fixture``). More generally, frameworks can detect that something (possibly a test fixture) is ready to catch unexpected errors by the presence and truth of ``"paste.throw_errors"`` (this is sometimes set outside of testing fixtures too, when an error-handling middleware is in place). Frameworks that want to expose the inner structure of the request may use ``"paste.testing_variables"``. This will be a dictionary -- any values put into that dictionary will become attributes of the response object. So if you do ``env["paste.testing_variables"]['template'] = template_name`` in your framework, then ``response.template`` will be ``template_name``. WebTest-2.0.18/docs/forms_fixt.py0000644000000000000000000000111112464666730015347 0ustar rootroot# -*- coding: utf-8 -*- from webtest.debugapp import make_debug_app from webtest.app import TestApp from doctest import ELLIPSIS from doctest import NORMALIZE_WHITESPACE import os dirname = os.path.dirname(__file__) def setup_test(test): app = make_debug_app({}, form=os.path.join(dirname, 'form.html'), show_form=True) test.globs['app'] = TestApp(app) for example in test.examples: example.options.setdefault(ELLIPSIS, 1) example.options.setdefault(NORMALIZE_WHITESPACE, 1) setup_test.__test__ = False WebTest-2.0.18/docs/testapp.rst0000644000000000000000000001147112464666730015041 0ustar rootrootTestApp ======= Making Requests --------------- To make a request, use: .. code-block:: python app.get('/path', [params], [headers], [extra_environ], ...) This call to :meth:`~webtest.TestApp.get` does a request for ``/path``, with any params, extra headers or WSGI environment keys that you indicate. This returns a :class:`~webtest.TestResponse` object, based on :class:`webob.response.Response`. It has some additional methods to make it easier to test. If you want to do a POST request, use: .. code-block:: python app.post('/path', {'vars': 'values'}, [headers], [extra_environ], [upload_files], ...) Specifically the second argument of :meth:`~webtest.TestApp.post` is the *body* of the request. You can pass in a dictionary (or dictionary-like object), or a string body (dictionary objects are turned into HTML form submissions). You can also pass in the keyword argument upload_files, which is a list of ``[(fieldname, filename, field_content)]``. File uploads use a different form submission data type to pass the structured data. You can use :meth:`~webtest.TestApp.put` and :meth:`~webtest.TestApp.delete` for PUT and DELETE requests. Making JSON Requests -------------------- Webtest provide some facilities to test json apis. The ``*_json`` methods will transform data to json before ``POST``/``PUT`` and add the correct ``Content-Type`` for you. Also Response have an attribute ``.json`` to allow you to retrieve json contents as a python dict. Doing *POST* request with :meth:`webtest.TestApp.post_json`: .. code-block:: python >>> resp = app.post_json('/resource/', dict(id=1, value='value')) >>> print(resp.request) POST /resource/ HTTP/1.0 Content-Length: 27 Content-Type: application/json ... >>> resp.json == {'id': 1, 'value': 'value'} True Doing *GET* request with :meth:`webtest.TestApp.get` and using :attr:`webtest.response.json`: To just parse body of the response, use Response.json: .. code-block:: python >>> resp = app.get('/resource/1/') >>> print(resp.request) GET /resource/1/ HTTP/1.0 ... >>> resp.json == {'id': 1, 'value': 'value'} True Modifying the Environment & Simulating Authentication ------------------------------------------------------ The best way to simulate authentication is if your application looks in ``environ['REMOTE_USER']`` to see if someone is authenticated. Then you can simply set that value, like: .. code-block:: python app.get('/secret', extra_environ=dict(REMOTE_USER='bob')) If you want *all* your requests to have this key, do: .. code-block:: python app = TestApp(my_app, extra_environ=dict(REMOTE_USER='bob')) If you have to use HTTP authorization you can use the ``.authorization`` property to set the ``HTTP_AUTHORIZATION`` key of the extra_environ dictionnary: .. code-block:: python app = TestApp(my_app) app.authorization = ('Basic', ('user', 'password')) Only Basic auth is supported for now. Testing a non wsgi application ------------------------------ You can use WebTest to test an application on a real web server. Just pass an url to the `TestApp` instead of a WSGI application:: app = TestApp('http://my.cool.websi.te') You can also use the ``WEBTEST_TARGET_URL`` env var to switch from a WSGI application to a real server without having to modify your code:: os.environ['WEBTEST_TARGET_URL'] = 'http://my.cool.websi.te' app = TestApp(wsgiapp) # will use the WEBTEST_TARGET_URL instead of the wsgiapp By default the proxy will use ``httplib`` but you can use other backends by adding an anchor to your url:: app = TestApp('http://my.cool.websi.te#urllib3') app = TestApp('http://my.cool.websi.te#requests') app = TestApp('http://my.cool.websi.te#restkit') What Is Tested By Default -------------------------- A key concept behind WebTest is that there's lots of things you shouldn't have to check everytime you do a request. It is assumed that the response will either be a 2xx or 3xx response; if it isn't an exception will be raised (you can override this for a request, of course). The WSGI application is tested for WSGI compliance with a slightly modified version of `wsgiref.validate `_ (modified to support arguments to ``InputWrapper.readline``) automatically. Also it checks that nothing is printed to the ``environ['wsgi.errors']`` error stream, which typically indicates a problem (one that would be non-fatal in a production situation, but if you are testing is something you should avoid). To indicate another status is expected, use the keyword argument ``status=404`` to (for example) check that it is a 404 status, or ``status="*"`` to allow any status, or ``status="400 Custom Bad Request"`` to use custom reason phrase. If you expect errors to be printed, use ``expect_errors=True``. WebTest-2.0.18/docs/contributing.rst0000755000000000000000000000655012464666730016075 0ustar rootroot============================= Contribute to webtest project ============================= Getting started =============== Get your working copy : .. code-block:: bash $ git clone https://github.com/Pylons/webtest.git $ cd webtest $ virtualenv . $ . bin/activate $ python setup.py dev Now, you can hack. Execute tests ============= .. code-block:: bash $ bin/nosetests Doctest: forms.rst ... ok Doctest: index.rst ... ok ... test_url_class (tests.test_testing.TestTesting) ... ok tests.test_testing.test_print_unicode ... °C ok Name Stmts Miss Cover Missing ------------------------------------------------ webtest 18 0 100% webtest.app 603 92 85% 48, 61-62, 94, 98, 212-221, 264-265, 268-272, 347, 379-386, 422, 426-428, 432-434, 455, 463, 471, 473, 488, 496-497, 515, 520-527, 548, 553-554, 558-559, 577, 592, 597-598, 618, 624, 661-664, 742, 808, 872, 940-941, 945-948, 961-964, 975, 982, 995, 1000, 1006, 1010, 1049, 1051, 1095-1096, 1118-1119, 1122-1127, 1135-1136, 1148, 1155-1160, 1175 webtest.compat 50 11 78% 28-34, 55-56, 61-62 webtest.debugapp 58 0 100% webtest.ext 80 0 100% webtest.forms 324 23 93% 23, 49, 58, 61, 92, 116, 177, 205, 411, 478, 482-486, 491-493, 522, 538, 558-561 webtest.http 78 0 100% webtest.lint 215 45 79% 135, 176, 214-216, 219-224, 227-231, 234, 243-244, 247, 250-251, 254, 263-264, 270, 274, 307, 311, 335, 359, 407, 424-427, 441-444, 476-479, 493, 508 webtest.sel 479 318 34% 38-39, 45-46, 64-78, 88-108, 120, 126, 151-153, 156-158, 164-165, 168-191, 194-201, 219-231, 236, 240, 243-259, 263-297, 301-306, 316-326, 331-336, 340, 344, 347-352, 357-359, 364, 392-394, 397-404, 408, 412-417, 421, 425-426, 430, 434, 438, 442, 445, 448-457, 470-480, 483-485, 488, 492, 495, 503, 506, 515-516, 520, 524, 528, 533, 538, 542-544, 547, 560-565, 576, 579, 582, 593-596, 599-602, 605-606, 617-620, 623-642, 668-677, 680-688, 715, 720, 732, 735, 744-754, 757-762, 770-779, 791, 794, 805-809, 813-826, 838-842 webtest.utils 99 11 89% 19-20, 23, 26, 32, 38, 100, 109, 152-154 ------------------------------------------------ TOTAL 2004 500 75% ---------------------------------------------------------------------- Ran 70 tests in 14.940s Use tox to test many Python versions ==================================== `Tox `_ installation : .. code-block:: bash $ pip install tox $ tox Launch tests with *tox* : .. code-block:: bash $ bin/tox py26: commands succeeded py27: commands succeeded py32: commands succeeded py33: commands succeeded To execute test on all python versions, you need to have ``python2.6``, ``python2.7``, ``python3.2`` and ``python3.3`` in your ``PATH``. Generate documentation ====================== .. code-block:: bash $ pip install Sphinx $ cd docs $ make html ../bin/sphinx-build -b html -d _build/doctrees . _build/html Running Sphinx v1.1.3 loading pickled environment... done ... build succeeded, 3 warnings. Build finished. The HTML pages are in _build/html. Tips ==== You can use :doc:`debugapp` object to test *webtest*. WebTest-2.0.18/docs/changelog.rst0000755000000000000000000003075012464666730015314 0ustar rootrootNews ==== 2.0.18 (2015-02-05) ------------------- - Avoid deprecation warning with py3.4 2.0.17 (2014-12-20) ------------------- - Properly check for default cookiejar arguments [Julian Berman] - Avoid raising encoding errors from debugapp (needed to use with WSGIProxy2) [Laurence Rowe] 2.0.16 (2014-09-19) ------------------- - Fixed #110. Forced values for Radio inputs are no longer ignored by value property on get. [bayprogrammer] - Added method TestApp.set_parser_features to change the parser_features used by BeautifulSoup. [tomasmoreyra] - Added app.set_cookie [luhn] 2.0.15 (2014-04-17) ------------------- - Fixed #73. Python < 2.6.5 does not support unicode as keyword arguments names. [Stepan Kolesnik] - Fixed #84 Application cookies for localhost are no longer ignored [gawel] - Fixed #89 remove WSGIWarning: You are not supposed to send a body in a DELETE request because we now have a good reason for that. See http://bit.ly/1tb3yxW [gawel] - Fixed #92 You can now override TestApp.JSONEncoder to use a custom encoder [gawel] - Fixed #93 Support basic authentication [gawel] - Fixed #103 Broken "Edit me on GitHub" links in documentation [gawel] - Fixed #106 Make wrapping the app in the lint middleware optional [dmlayton] - Fixed #107 Explicit error message when WSGIProxy2 is not installer [gawel] - Fixed #108 cgi.parse_qsl is pending deprecation [gawel] 2.0.14 (2014-01-23) ------------------- - Allow `.select()` on s. [Markus Bertheau] 2.0.13 (2014-01-23) ------------------- - Allow selecting [Marius Gedminas] 2.0.4 (2013-03-28) ------------------ * Correctly handle