From 03d9c55e384fb1ba37b22bf05ded8ef3d4ae13aa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89loi=20Rivard?= Date: Sat, 12 Aug 2023 13:09:28 +0200 Subject: [PATCH] chore: migrate to pytest - replace setUp/tearDown with pytest fixtures - rename test classes to use the pytest convention - use pytest assertions Co-authored-by: Glandos --- ihatemoney/tests/api_test.py | 212 ++++---- ihatemoney/tests/budget_test.py | 470 +++++++++--------- .../tests/common/ihatemoney_testcase.py | 42 +- ihatemoney/tests/conftest.py | 60 +++ ihatemoney/tests/history_test.py | 434 ++++++++-------- ihatemoney/tests/import_test.py | 164 +++--- ihatemoney/tests/main_test.py | 133 +++-- setup.cfg | 2 +- 8 files changed, 751 insertions(+), 766 deletions(-) create mode 100644 ihatemoney/tests/conftest.py diff --git a/ihatemoney/tests/api_test.py b/ihatemoney/tests/api_test.py index 73d917da1..f4c133322 100644 --- a/ihatemoney/tests/api_test.py +++ b/ihatemoney/tests/api_test.py @@ -1,13 +1,12 @@ import base64 import datetime import json -import unittest from ihatemoney.tests.common.help_functions import em_surround from ihatemoney.tests.common.ihatemoney_testcase import IhatemoneyTestCase -class APITestCase(IhatemoneyTestCase): +class TestAPI(IhatemoneyTestCase): """Tests the API""" @@ -57,7 +56,7 @@ def test_cors_requests(self): resp = self.client.options( "/api/projects/raclette", headers=self.get_auth("raclette") ) - self.assertEqual(resp.headers["Access-Control-Allow-Origin"], "*") + assert resp.headers["Access-Control-Allow-Origin"] == "*" def test_basic_auth(self): # create a project @@ -94,32 +93,32 @@ def test_project(self): }, ) - self.assertEqual(400, resp.status_code) - self.assertEqual( - '{"contact_email": ["Invalid email address."]}\n', resp.data.decode("utf-8") + assert 400 == resp.status_code + assert '{"contact_email": ["Invalid email address."]}\n' == resp.data.decode( + "utf-8" ) # create it with self.app.mail.record_messages() as outbox: resp = self.api_create("raclette") - self.assertEqual(201, resp.status_code) + assert 201 == resp.status_code # Check that email messages have been sent. - self.assertEqual(len(outbox), 1) - self.assertEqual(outbox[0].recipients, ["raclette@notmyidea.org"]) + assert len(outbox) == 1 + assert outbox[0].recipients == ["raclette@notmyidea.org"] # create it twice should return a 400 resp = self.api_create("raclette") - self.assertEqual(400, resp.status_code) - self.assertIn("id", json.loads(resp.data.decode("utf-8"))) + assert 400 == resp.status_code + assert "id" in json.loads(resp.data.decode("utf-8")) # get information about it resp = self.client.get( "/api/projects/raclette", headers=self.get_auth("raclette") ) - self.assertEqual(200, resp.status_code) + assert 200 == resp.status_code expected = { "members": [], "name": "raclette", @@ -129,7 +128,7 @@ def test_project(self): "logging_preference": 1, } decoded_resp = json.loads(resp.data.decode("utf-8")) - self.assertDictEqual(decoded_resp, expected) + assert decoded_resp == expected # edit should fail if we don't provide the current private code resp = self.client.put( @@ -143,7 +142,7 @@ def test_project(self): }, headers=self.get_auth("raclette"), ) - self.assertEqual(400, resp.status_code) + assert 400 == resp.status_code # edit should fail if we provide the wrong private code resp = self.client.put( @@ -158,7 +157,7 @@ def test_project(self): }, headers=self.get_auth("raclette"), ) - self.assertEqual(400, resp.status_code) + assert 400 == resp.status_code # edit with the correct private code should work resp = self.client.put( @@ -173,13 +172,13 @@ def test_project(self): }, headers=self.get_auth("raclette"), ) - self.assertEqual(200, resp.status_code) + assert 200 == resp.status_code resp = self.client.get( "/api/projects/raclette", headers=self.get_auth("raclette") ) - self.assertEqual(200, resp.status_code) + assert 200 == resp.status_code expected = { "name": "The raclette party", "contact_email": "yeah@notmyidea.org", @@ -189,7 +188,7 @@ def test_project(self): "logging_preference": 1, } decoded_resp = json.loads(resp.data.decode("utf-8")) - self.assertDictEqual(decoded_resp, expected) + assert decoded_resp == expected # password change is possible via API resp = self.client.put( @@ -204,12 +203,12 @@ def test_project(self): headers=self.get_auth("raclette"), ) - self.assertEqual(200, resp.status_code) + assert 200 == resp.status_code resp = self.client.get( "/api/projects/raclette", headers=self.get_auth("raclette", "tartiflette") ) - self.assertEqual(200, resp.status_code) + assert 200 == resp.status_code # delete should work resp = self.client.delete( @@ -220,21 +219,21 @@ def test_project(self): resp = self.client.get( "/api/projects/raclette", headers=self.get_auth("raclette") ) - self.assertEqual(401, resp.status_code) + assert 401 == resp.status_code def test_token_creation(self): """Test that token of project is generated""" # Create project resp = self.api_create("raclette") - self.assertEqual(201, resp.status_code) + assert 201 == resp.status_code # Get token resp = self.client.get( "/api/projects/raclette/token", headers=self.get_auth("raclette") ) - self.assertEqual(200, resp.status_code) + assert 200 == resp.status_code decoded_resp = json.loads(resp.data.decode("utf-8")) @@ -243,7 +242,7 @@ def test_token_creation(self): "/api/projects/raclette/token", headers={"Authorization": f"Basic {decoded_resp['token']}"}, ) - self.assertEqual(200, resp.status_code) + assert 200 == resp.status_code # We shouldn't be able to edit project without private code resp = self.client.put( @@ -256,9 +255,9 @@ def test_token_creation(self): }, headers={"Authorization": f"Basic {decoded_resp['token']}"}, ) - self.assertEqual(400, resp.status_code) + assert 400 == resp.status_code expected_resp = {"current_password": ["This field is required."]} - self.assertEqual(expected_resp, json.loads(resp.data.decode("utf-8"))) + assert expected_resp == json.loads(resp.data.decode("utf-8")) def test_token_login(self): resp = self.api_create("raclette") @@ -269,7 +268,7 @@ def test_token_login(self): decoded_resp = json.loads(resp.data.decode("utf-8")) resp = self.client.get(f"/raclette/join/{decoded_resp['token']}") # Test that we are redirected. - self.assertEqual(302, resp.status_code) + assert 302 == resp.status_code def test_member(self): # create a project @@ -281,7 +280,7 @@ def test_member(self): ) self.assertStatus(200, req) - self.assertEqual("[]\n", req.data.decode("utf-8")) + assert "[]\n" == req.data.decode("utf-8") # add a member req = self.client.post( @@ -292,7 +291,7 @@ def test_member(self): # the id of the new member should be returned self.assertStatus(201, req) - self.assertEqual("1\n", req.data.decode("utf-8")) + assert "1\n" == req.data.decode("utf-8") # the list of participants should contain one member req = self.client.get( @@ -300,7 +299,7 @@ def test_member(self): ) self.assertStatus(200, req) - self.assertEqual(len(json.loads(req.data.decode("utf-8"))), 1) + assert len(json.loads(req.data.decode("utf-8"))) == 1 # Try to add another member with the same name. req = self.client.post( @@ -325,8 +324,8 @@ def test_member(self): ) self.assertStatus(200, req) - self.assertEqual("Fred", json.loads(req.data.decode("utf-8"))["name"]) - self.assertEqual(2, json.loads(req.data.decode("utf-8"))["weight"]) + assert "Fred" == json.loads(req.data.decode("utf-8"))["name"] + assert 2 == json.loads(req.data.decode("utf-8"))["weight"] # edit this member with same information # (test PUT idemopotence) @@ -350,7 +349,7 @@ def test_member(self): "/api/projects/raclette/members/1", headers=self.get_auth("raclette") ) self.assertStatus(200, req) - self.assertEqual(False, json.loads(req.data.decode("utf-8"))["activated"]) + assert not json.loads(req.data.decode("utf-8"))["activated"] # re-activate the participant req = self.client.put( @@ -363,7 +362,7 @@ def test_member(self): "/api/projects/raclette/members/1", headers=self.get_auth("raclette") ) self.assertStatus(200, req) - self.assertEqual(True, json.loads(req.data.decode("utf-8"))["activated"]) + assert json.loads(req.data.decode("utf-8"))["activated"] # delete a member @@ -379,7 +378,7 @@ def test_member(self): ) self.assertStatus(200, req) - self.assertEqual("[]\n", req.data.decode("utf-8")) + assert "[]\n" == req.data.decode("utf-8") def test_bills(self): # create a project @@ -396,7 +395,7 @@ def test_bills(self): ) self.assertStatus(200, req) - self.assertEqual("[]\n", req.data.decode("utf-8")) + assert "[]\n" == req.data.decode("utf-8") # add a bill req = self.client.post( @@ -414,7 +413,7 @@ def test_bills(self): # should return the id self.assertStatus(201, req) - self.assertEqual(req.data.decode("utf-8"), "1\n") + assert req.data.decode("utf-8") == "1\n" # get this bill details req = self.client.get( @@ -439,19 +438,19 @@ def test_bills(self): } got = json.loads(req.data.decode("utf-8")) - self.assertEqual( - datetime.date.today(), - datetime.datetime.strptime(got["creation_date"], "%Y-%m-%d").date(), + assert ( + datetime.date.today() + == datetime.datetime.strptime(got["creation_date"], "%Y-%m-%d").date() ) del got["creation_date"] - self.assertDictEqual(expected, got) + assert expected == got # the list of bills should length 1 req = self.client.get( "/api/projects/raclette/bills", headers=self.get_auth("raclette") ) self.assertStatus(200, req) - self.assertEqual(1, len(json.loads(req.data.decode("utf-8")))) + assert 1 == len(json.loads(req.data.decode("utf-8"))) # edit with errors should return an error req = self.client.put( @@ -468,9 +467,7 @@ def test_bills(self): ) self.assertStatus(400, req) - self.assertEqual( - '{"date": ["This field is required."]}\n', req.data.decode("utf-8") - ) + assert '{"date": ["This field is required."]}\n' == req.data.decode("utf-8") # edit a bill req = self.client.put( @@ -510,12 +507,12 @@ def test_bills(self): } got = json.loads(req.data.decode("utf-8")) - self.assertEqual( - creation_date, - datetime.datetime.strptime(got["creation_date"], "%Y-%m-%d").date(), + assert ( + creation_date + == datetime.datetime.strptime(got["creation_date"], "%Y-%m-%d").date() ) del got["creation_date"] - self.assertDictEqual(expected, got) + assert expected == got # delete a bill req = self.client.delete( @@ -562,7 +559,7 @@ def test_bills_with_calculation(self): # should return the id self.assertStatus(201, req) - self.assertEqual(req.data.decode("utf-8"), "{}\n".format(id)) + assert req.data.decode("utf-8") == "{}\n".format(id) # get this bill's details req = self.client.get( @@ -588,12 +585,12 @@ def test_bills_with_calculation(self): } got = json.loads(req.data.decode("utf-8")) - self.assertEqual( - datetime.date.today(), - datetime.datetime.strptime(got["creation_date"], "%Y-%m-%d").date(), + assert ( + datetime.date.today() + == datetime.datetime.strptime(got["creation_date"], "%Y-%m-%d").date() ) del got["creation_date"] - self.assertDictEqual(expected, got) + assert expected == got # should raise errors erroneous_amounts = [ @@ -621,19 +618,19 @@ def test_bills_with_calculation(self): def test_currencies(self): # check /currencies for list of supported currencies resp = self.client.get("/api/currencies") - self.assertEqual(200, resp.status_code) - self.assertIn("XXX", json.loads(resp.data.decode("utf-8"))) + assert 200 == resp.status_code + assert "XXX" in json.loads(resp.data.decode("utf-8")) # create project with a default currency resp = self.api_create("raclette", default_currency="EUR") - self.assertEqual(201, resp.status_code) + assert 201 == resp.status_code # get information about it resp = self.client.get( "/api/projects/raclette", headers=self.get_auth("raclette") ) - self.assertEqual(200, resp.status_code) + assert 200 == resp.status_code expected = { "members": [], "name": "raclette", @@ -643,7 +640,7 @@ def test_currencies(self): "logging_preference": 1, } decoded_resp = json.loads(resp.data.decode("utf-8")) - self.assertDictEqual(decoded_resp, expected) + assert decoded_resp == expected # Add participants self.api_add_member("raclette", "zorglub") @@ -666,7 +663,7 @@ def test_currencies(self): # should return the id self.assertStatus(201, req) - self.assertEqual(req.data.decode("utf-8"), "1\n") + assert req.data.decode("utf-8") == "1\n" # get this bill details req = self.client.get( @@ -691,12 +688,12 @@ def test_currencies(self): } got = json.loads(req.data.decode("utf-8")) - self.assertEqual( - datetime.date.today(), - datetime.datetime.strptime(got["creation_date"], "%Y-%m-%d").date(), + assert ( + datetime.date.today() + == datetime.datetime.strptime(got["creation_date"], "%Y-%m-%d").date() ) del got["creation_date"] - self.assertDictEqual(expected, got) + assert expected == got # Change bill amount and currency req = self.client.put( @@ -737,7 +734,7 @@ def test_currencies(self): got = json.loads(req.data.decode("utf-8")) del got["creation_date"] - self.assertDictEqual(expected, got) + assert expected == got # Add a bill with yet another currency req = self.client.post( @@ -755,7 +752,7 @@ def test_currencies(self): # should return the id self.assertStatus(201, req) - self.assertEqual(req.data.decode("utf-8"), "2\n") + assert req.data.decode("utf-8") == "2\n" # Try to remove default project currency, it should fail req = self.client.put( @@ -770,9 +767,9 @@ def test_currencies(self): headers=self.get_auth("raclette"), ) self.assertStatus(400, req) - self.assertIn("This project cannot be set", req.data.decode("utf-8")) - self.assertIn( - "because it contains bills in multiple currencies", req.data.decode("utf-8") + assert "This project cannot be set" in req.data.decode("utf-8") + assert "because it contains bills in multiple currencies" in req.data.decode( + "utf-8" ) def test_statistics(self): @@ -801,33 +798,30 @@ def test_statistics(self): "/api/projects/raclette/statistics", headers=self.get_auth("raclette") ) self.assertStatus(200, req) - self.assertEqual( - [ - { - "balance": 12.5, - "member": { - "activated": True, - "id": 1, - "name": "zorglub", - "weight": 1.0, - }, - "paid": 25.0, - "spent": 12.5, + assert [ + { + "balance": 12.5, + "member": { + "activated": True, + "id": 1, + "name": "zorglub", + "weight": 1.0, }, - { - "balance": -12.5, - "member": { - "activated": True, - "id": 2, - "name": "fred", - "weight": 1.0, - }, - "paid": 0, - "spent": 12.5, + "paid": 25.0, + "spent": 12.5, + }, + { + "balance": -12.5, + "member": { + "activated": True, + "id": 2, + "name": "fred", + "weight": 1.0, }, - ], - json.loads(req.data.decode("utf-8")), - ) + "paid": 0, + "spent": 12.5, + }, + ] == json.loads(req.data.decode("utf-8")) def test_username_xss(self): # create a project @@ -839,7 +833,7 @@ def test_username_xss(self): self.api_add_member("raclette", "