FlaskTester 3.4__tar.gz → 3.6__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: FlaskTester
3
- Version: 3.4
3
+ Version: 3.6
4
4
  Summary: Pytest fixtures for Flask internal and external authenticated tests
5
5
  Author-email: Fabien Coelho <flask.tester@coelho.net>
6
6
  License: CC0
@@ -52,7 +52,7 @@ Only one set of tests is needed, switching from internal to external is
52
52
  achieved through environment variables.
53
53
 
54
54
  ![Status](https://github.com/zx80/flask-tester/actions/workflows/package.yml/badge.svg?branch=main&style=flat)
55
- ![Tests](https://img.shields.io/badge/tests-13%20✓-success)
55
+ ![Tests](https://img.shields.io/badge/tests-14%20✓-success)
56
56
  ![Coverage](https://img.shields.io/badge/coverage-100%25-success)
57
57
  ![Issues](https://img.shields.io/github/issues/zx80/flask-tester?style=flat)
58
58
  ![Python](https://img.shields.io/badge/python-3-informational)
@@ -107,7 +107,7 @@ This can be run against a (local) server:
107
107
  export TEST_SEED="some-random-data" # shared test seed
108
108
  flask --app app:app run & # start flask app
109
109
  pid=$! # keep pid
110
- export FLASK_TESTER_URL="http://localhost:5000" # set app local url
110
+ export FLASK_TESTER_APP="http://localhost:5000" # set app local url
111
111
  pytest test.py # run external tests
112
112
  kill $pid # stop app with pid
113
113
  ```
@@ -115,7 +115,7 @@ kill $pid # stop app with pid
115
115
  Or locally with the Flask internal test infrastructure:
116
116
 
117
117
  ```shell
118
- export FLASK_TESTER_APP="app:app" # set app module
118
+ export FLASK_TESTER_APP="app:app" # set app package
119
119
  pytest test.py # run internal tests
120
120
  ```
121
121
 
@@ -8,4 +8,5 @@ FlaskTester.egg-info/SOURCES.txt
8
8
  FlaskTester.egg-info/dependency_links.txt
9
9
  FlaskTester.egg-info/requires.txt
10
10
  FlaskTester.egg-info/top_level.txt
11
- tests/test.py
11
+ tests/test_app.py
12
+ tests/test_app2.py
@@ -1,7 +1,6 @@
1
1
  """FlaskTester - Pytest fixtures for Flask authenticated internal and external tests.
2
2
 
3
- This is needed when testing this module, but may not be desirable when it is
4
- used depending on the ``assert``: PYTEST_DONT_REWRITE
3
+ PYTEST_DONT_REWRITE: local assertions are really that, not pytest assertions.
5
4
  """
6
5
 
7
6
  import os
@@ -25,6 +24,20 @@ class AuthError(FlaskTesterError):
25
24
  pass
26
25
 
27
26
 
27
+ class _AssertError(FlaskTesterError):
28
+ """User assertion Exception, only for internal testing."""
29
+ pass
30
+
31
+
32
+ def _raiseError(msg: str):
33
+ """Undocumented switch for FlaskTester own tests."""
34
+ log.error(msg)
35
+ if "FLASK_TESTER_TESTING" in os.environ:
36
+ raise _AssertError(msg)
37
+ else: # pragma: no cover # cannot cover an expected pytest failure!
38
+ pytest.fail(msg)
39
+
40
+
28
41
  class Authenticator:
29
42
  """Manage HTTP request authentication.
30
43
 
@@ -336,14 +349,12 @@ class Client:
336
349
  # check status
337
350
  if status is not None:
338
351
  if res.status_code != status: # show error before aborting
339
- log.error(f"bad {status} result: {res.status_code} {res.text[:512]}")
340
- assert res.status_code == status, f"unexpected status {res.status_code}, expecting {status}"
352
+ _raiseError(f"bad {status} result: {res.status_code} {res.text[:512]}...")
341
353
 
342
354
  # check content
343
355
  if content is not None:
344
356
  if not re.search(content, res.text, re.DOTALL):
345
- log.error(f"cannot find {content} in {res.text}")
346
- assert False, f"expected content {content} not found in {res.text}"
357
+ _raiseError(f"cannot find {content} in {res.text[:512]}...")
347
358
 
348
359
  return res
349
360
 
@@ -521,15 +532,14 @@ def _ft_client(authenticator):
521
532
  default_login = os.environ.get("FLASK_TESTER_DEFAULT", None)
522
533
  client: Client
523
534
 
524
- if "FLASK_TESTER_URL" in os.environ:
525
-
526
- app_url = os.environ["FLASK_TESTER_URL"]
527
- client = RequestClient(authenticator, app_url, default_login)
528
-
529
- elif "FLASK_TESTER_APP" in os.environ:
535
+ app_def = os.environ.get("FLASK_TESTER_URL", "app")
536
+ app_def = os.environ.get("FLASK_TESTER_APP", app_def)
530
537
 
538
+ if app_def.startswith("http://") or app_def.startswith("https://"):
539
+ client = RequestClient(authenticator, app_def, default_login)
540
+ else:
531
541
  # load app package
532
- pkg_name, app = os.environ["FLASK_TESTER_APP"], None
542
+ pkg_name, app = app_def, None
533
543
  app_names = ["app", "application", "create_app", "make_app"]
534
544
  if ":" in pkg_name: # override defaults
535
545
  pkg_name, app_name = pkg_name.split(":", 1)
@@ -546,20 +556,17 @@ def _ft_client(authenticator):
546
556
  raise FlaskTesterError(f"cannot find Flask app in {pkg_name}")
547
557
  client = FlaskClient(authenticator, app.test_client(), default_login)
548
558
 
549
- else:
550
-
551
- raise FlaskTesterError("no Flask application to test")
552
-
553
559
  return client
554
560
 
555
561
  @pytest.fixture
556
562
  def ft_client(ft_authenticator):
557
563
  """Pytest Fixture: ft_client.
558
564
 
559
- Target environment variable, one **must** be defined:
565
+ Target environment variable:
560
566
 
561
- - ``FLASK_TESTER_URL``: application HTTP base URL, eg ``http://localhost:5000``.
562
- - ``FLASK_TESTER_APP``: Flask application, eg ``app:create_app``.
567
+ - ``FLASK_TESTER_APP``: find the Flask application, eg
568
+ ``app:create_app`` for an internal test, or
569
+ ``http://localhost:5000`` for an external test.
563
570
 
564
571
  Other environment variable:
565
572
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: FlaskTester
3
- Version: 3.4
3
+ Version: 3.6
4
4
  Summary: Pytest fixtures for Flask internal and external authenticated tests
5
5
  Author-email: Fabien Coelho <flask.tester@coelho.net>
6
6
  License: CC0
@@ -52,7 +52,7 @@ Only one set of tests is needed, switching from internal to external is
52
52
  achieved through environment variables.
53
53
 
54
54
  ![Status](https://github.com/zx80/flask-tester/actions/workflows/package.yml/badge.svg?branch=main&style=flat)
55
- ![Tests](https://img.shields.io/badge/tests-13%20✓-success)
55
+ ![Tests](https://img.shields.io/badge/tests-14%20✓-success)
56
56
  ![Coverage](https://img.shields.io/badge/coverage-100%25-success)
57
57
  ![Issues](https://img.shields.io/github/issues/zx80/flask-tester?style=flat)
58
58
  ![Python](https://img.shields.io/badge/python-3-informational)
@@ -107,7 +107,7 @@ This can be run against a (local) server:
107
107
  export TEST_SEED="some-random-data" # shared test seed
108
108
  flask --app app:app run & # start flask app
109
109
  pid=$! # keep pid
110
- export FLASK_TESTER_URL="http://localhost:5000" # set app local url
110
+ export FLASK_TESTER_APP="http://localhost:5000" # set app local url
111
111
  pytest test.py # run external tests
112
112
  kill $pid # stop app with pid
113
113
  ```
@@ -115,7 +115,7 @@ kill $pid # stop app with pid
115
115
  Or locally with the Flask internal test infrastructure:
116
116
 
117
117
  ```shell
118
- export FLASK_TESTER_APP="app:app" # set app module
118
+ export FLASK_TESTER_APP="app:app" # set app package
119
119
  pytest test.py # run internal tests
120
120
  ```
121
121
 
@@ -9,7 +9,7 @@ Only one set of tests is needed, switching from internal to external is
9
9
  achieved through environment variables.
10
10
 
11
11
  ![Status](https://github.com/zx80/flask-tester/actions/workflows/package.yml/badge.svg?branch=main&style=flat)
12
- ![Tests](https://img.shields.io/badge/tests-13%20✓-success)
12
+ ![Tests](https://img.shields.io/badge/tests-14%20✓-success)
13
13
  ![Coverage](https://img.shields.io/badge/coverage-100%25-success)
14
14
  ![Issues](https://img.shields.io/github/issues/zx80/flask-tester?style=flat)
15
15
  ![Python](https://img.shields.io/badge/python-3-informational)
@@ -64,7 +64,7 @@ This can be run against a (local) server:
64
64
  export TEST_SEED="some-random-data" # shared test seed
65
65
  flask --app app:app run & # start flask app
66
66
  pid=$! # keep pid
67
- export FLASK_TESTER_URL="http://localhost:5000" # set app local url
67
+ export FLASK_TESTER_APP="http://localhost:5000" # set app local url
68
68
  pytest test.py # run external tests
69
69
  kill $pid # stop app with pid
70
70
  ```
@@ -72,7 +72,7 @@ kill $pid # stop app with pid
72
72
  Or locally with the Flask internal test infrastructure:
73
73
 
74
74
  ```shell
75
- export FLASK_TESTER_APP="app:app" # set app module
75
+ export FLASK_TESTER_APP="app:app" # set app package
76
76
  pytest test.py # run internal tests
77
77
  ```
78
78
 
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "FlaskTester"
7
- version = "3.4"
7
+ version = "3.6"
8
8
  authors = [ { name = "Fabien Coelho", email = "flask.tester@coelho.net" } ]
9
9
  description = "Pytest fixtures for Flask internal and external authenticated tests"
10
10
  readme = "README.md"
@@ -15,6 +15,7 @@ logging.basicConfig(level=logging.INFO)
15
15
 
16
16
  # set authn for ft_authenticator
17
17
  os.environ.update(
18
+ FLASK_TESTER_TESTING="*",
18
19
  FLASK_TESTER_ALLOW="bearer basic param none",
19
20
  FLASK_TESTER_AUTH=",".join(f"{l}:{p}" for l, p in secret.PASSES.items()),
20
21
  )
@@ -109,25 +110,32 @@ def test_admin(api):
109
110
  api.get("/admin", 403, login="hobbes", auth=auth)
110
111
  api.get("/admin", 401, login="moe", auth=auth)
111
112
  api.get("/admin", 401, login=None, auth=auth)
113
+ # test status error
112
114
  try:
113
115
  api.get("/admin", status=599, login="calvin", auth=auth)
114
116
  pytest.fail("assert on status must fail") # pragma: no cover
115
- except AssertionError as e:
117
+ except ft._AssertError as e:
116
118
  assert "200" in str(e)
119
+ # test content error
117
120
  try:
118
121
  api.get("/admin", status=200, login="calvin", auth=auth, content="NOT THERE")
119
122
  pytest.fail("assert on content must fail") # pragma: no cover
120
- except AssertionError as e:
123
+ except ft._AssertError as e:
121
124
  assert "NOT THERE" in str(e)
122
125
 
123
126
  def test_errors(api):
124
127
  # these schemes are not allowed
125
- for scheme in ("header", "cookie", "fake", "tparam", "unexpected"):
128
+ for scheme in ("header", "cookie", "fake", "tparam"):
126
129
  try:
127
130
  api.get("/login", login="calvin", auth=scheme)
128
131
  pytest.fail("must raise an exception") # pragma: no cover
129
132
  except ft.AuthError as e:
130
- assert True, "expected error"
133
+ assert "auth is not allowed" in str(e)
134
+ try:
135
+ api.get("/login", login="calvin", auth="foobla")
136
+ pytest.fail("must raise an exception") # pragma: no cover
137
+ except ft.AuthError as e:
138
+ assert "unexpected auth" in str(e)
131
139
 
132
140
  def test_methods(api):
133
141
  res = api.get("/who-am-i", login="susie", status=200, cookies={"lang": "it"})
@@ -301,7 +309,6 @@ def test_client_fixture():
301
309
  # ft_client coverage
302
310
  auth = ft._ft_authenticator()
303
311
  # check and save env
304
- # assert "FLASK_TESTER_URL" not in os.environ
305
312
  url = None
306
313
  if "FLASK_TESTER_URL" in os.environ: # pragma: no cover
307
314
  url = os.environ["FLASK_TESTER_URL"]
@@ -310,12 +317,8 @@ def test_client_fixture():
310
317
  if "FLASK_TESTER_APP" in os.environ:
311
318
  app = os.environ["FLASK_TESTER_APP"]
312
319
  del os.environ["FLASK_TESTER_APP"]
313
- # no url nor app
314
- try:
315
- init = ft._ft_client(auth)
316
- pytest.fail("must fail without environment variables") # pragma: no cover
317
- except ft.FlaskTesterError:
318
- assert True, "expected error raised"
320
+ # no url nor app, defaults to "app"
321
+ init = ft._ft_client(auth)
319
322
  # url
320
323
  os.environ["FLASK_TESTER_URL"] = "http://localhost:5000"
321
324
  init = ft._ft_client(auth)
@@ -0,0 +1,28 @@
1
+ import os
2
+ import pytest
3
+ from FlaskTester import ft_client, ft_authenticator
4
+
5
+ os.environ.update(FLASK_TESTER_ALLOW="basic param none")
6
+
7
+ @pytest.fixture
8
+ def app(ft_client):
9
+ ft_client.setPass("calvin", "clv-pw")
10
+ ft_client.setCookie("calvin", "lang", "en")
11
+ ft_client.setPass("hobbes", "hbs-pw")
12
+ ft_client.setCookie("hobbes", "lang", "fr")
13
+ yield ft_client
14
+
15
+ def test_something(app):
16
+ # requires an authentication
17
+ app.get("/authenticated", 401, login=None)
18
+ res = app.get("/authenticated", 200, login="calvin")
19
+ assert "Hello" in res.text
20
+ app.get("/authenticated", 200, "Bonjour", login="hobbes")
21
+ # only allowed to calvin
22
+ app.get("/only-calvin", 401, login=None)
23
+ app.get("/only-calvin", 200, login="calvin")
24
+ app.get("/only-calvin", 403, login="hobbes")
25
+ # no authentication required, but depends on lang
26
+ res = app.get("/no-auth", 200, login="calvin", auth="none")
27
+ assert "Hello" in res.text
28
+ app.get("/no-auth", 200, "Bonjour", login="hobbes", auth="none")
File without changes
File without changes
File without changes