Repository: pogzyb/whodap (language: python)

Issue:
Remove asynctest
`asynctest` is no longer maintained and doesn't work with Python 3.11

https://github.com/Martiusweb/asynctest/issues/163


Discussion / hints:

Fix patch:
diff --git a/setup.cfg b/setup.cfg
index 6f9f6e3..62c214c 100644
--- a/setup.cfg
+++ b/setup.cfg
@@ -21,6 +21,8 @@ classifiers =
     Programming Language :: Python :: 3.7
     Programming Language :: Python :: 3.8
     Programming Language :: Python :: 3.9
+    Programming Language :: Python :: 3.10
+    Programming Language :: Python :: 3.11
     Programming Language :: Python :: 3 :: Only
 
 [options]
diff --git a/setup.py b/setup.py
index fec649a..e796e23 100644
--- a/setup.py
+++ b/setup.py
@@ -42,6 +42,7 @@ def get_version(location: str) -> str:
         'Programming Language :: Python :: 3.8',
         'Programming Language :: Python :: 3.9',
         'Programming Language :: Python :: 3.10',
+        'Programming Language :: Python :: 3.11',
         'Programming Language :: Python :: 3 :: Only',
     ],
     packages=['whodap'],
diff --git a/tox.ini b/tox.ini
index 5b08c17..7323f93 100644
--- a/tox.ini
+++ b/tox.ini
@@ -1,6 +1,6 @@
 [tox]
 envlist = py36, py37, py38, py39, py310
-minversion = 3.3.0
+minversion = 3.6.0
 isolated_build = true
 
 [gh-actions]
@@ -13,8 +13,9 @@ python =
 
 [testenv]
 deps =
-    asynctest >= 0.13.0
     pytest >= 6.2.5
     pytest-cov >= 3.0.0
+    pytest-mock >= 3.10.0
+    pytest-asyncio >= 0.20.3
 commands =
     pytest --cov-report xml --cov={envsitepackagesdir}/whodap
\ No newline at end of file


Test patch:
diff --git a/.github/workflows/run-build-and-test.yml b/.github/workflows/run-build-and-test.yml
index f112d98..3619a48 100644
--- a/.github/workflows/run-build-and-test.yml
+++ b/.github/workflows/run-build-and-test.yml
@@ -1,4 +1,4 @@
-name: Build
+name: build
 
 on:
   - push
@@ -13,7 +13,7 @@ jobs:
           - ubuntu-latest  # ubuntu-20.04
           - macos-latest  # macOS-11
           - windows-latest  # windows-2022
-        python-version: ['3.7', '3.8', '3.9', '3.10']
+        python-version: ['3.7', '3.8', '3.9', '3.10', '3.11']
 
     steps:
     - uses: actions/checkout@v3
diff --git a/tests/test_client.py b/tests/test_client.py
index 5218073..ac62065 100644
--- a/tests/test_client.py
+++ b/tests/test_client.py
@@ -1,27 +1,72 @@
-import asynctest
-import asynctest.mock as mock
-import ipaddress
+import asyncio
+import sys
+import unittest
+import unittest.mock as mock
+
+import pytest
 
 from whodap import DNSClient, IPv4Client, IPv6Client, ASNClient
 from whodap.errors import RateLimitError, NotFoundError, MalformedQueryError
 
+fake_http_response = "fake-http-response"
+
+links_a = [
+    {
+        "rel": "self",
+        "href": "https://an-rdap-server/domain/domain.com",
+        "type": "application/rdap+json",
+    },
+    {
+        "rel": "related",
+        "href": "https://the-authoritative-server/domain/domain.com",
+        "type": "application/rdap+json",
+    },
+]
+
+links_b = [
+    {
+        "rel": "self",
+        "href": "https://the-authoritative-server/domain/domain.com",
+        "type": "application/rdap+json",
+    }
+]
+
+if sys.version_info >= (3, 8):
 
-class TestDNSClient(asynctest.TestCase):
+    def async_mock_request():
+        mock_request = mock.AsyncMock(
+            status_code=200,
+            json=mock.Mock(return_value={"links": links_a}),
+            read=mock.Mock(return_value=b'{"test": "json"}'),
+        )
+        return mock_request
 
-    async def setUp(self) -> None:
-        self.dns_client = DNSClient.new_client()
-        self.aio_dns_client = await DNSClient.new_aio_client()
 
-    async def tearDown(self) -> None:
-        self.dns_client.close()
-        await self.aio_dns_client.aio_close()
+    def mock_http_client():
+        m = mock.AsyncMock(
+            is_closed=1,
+            get=mock.AsyncMock(return_value=fake_http_response)
+        )
+        return m
 
-    def test_build_query_url(self):
+
+    def sync_mock_request():
+        mock_request = mock.Mock(
+            status_code=200,
+            json=mock.Mock(return_value={"links": links_a}),
+            read=mock.Mock(return_value=b'{"test": "json"}'),
+        )
+        return mock_request
+
+
+    def test_build_query_url():
         expected_base_case = "http://some-url.com/domain/domain-name"
         output = DNSClient._build_query_href("http://some-url.com/", "domain-name")
         assert output == expected_base_case, f"{output} != {expected_base_case}"
         expected_absolute_case = "http://bad-example/domain/forward-slash-domain"
-        output = DNSClient._build_query_href("http://bad-example", "/forward-slash-domain")
+        output = DNSClient._build_query_href(
+            "http://bad-example", "/forward-slash-domain"
+        )
         assert output == expected_absolute_case, f"{output} != {expected_absolute_case}"
         # ipv4
         expected_base_case = "http://some-url.com/ip/8.8.8.8"
@@ -29,153 +74,138 @@ def test_build_query_url(self):
         assert output == expected_base_case, f"{output} != {expected_base_case}"
         # ipv6
         expected_base_case = "http://some-url.com/ip/2001:4860:4860::8844"
-        output = IPv6Client._build_query_href("http://some-url.com/", "2001:4860:4860::8844")
+        output = IPv6Client._build_query_href(
+            "http://some-url.com/", "2001:4860:4860::8844"
+        )
         assert output == expected_base_case, f"{output} != {expected_base_case}"
         # asn
         expected_base_case = "http://some-url.com/autnum/12345"
         output = ASNClient._build_query_href("http://some-url.com/", "12345")
         assert output == expected_base_case, f"{output} != {expected_base_case}"
 
-    def test_check_status(self):
+
+    def test_check_status():
         assert DNSClient._check_status_code(200) is None
-        self.assertRaises(RateLimitError, DNSClient._check_status_code, 429)
-        self.assertRaises(NotFoundError, DNSClient._check_status_code, 404)
-        self.assertRaises(MalformedQueryError, DNSClient._check_status_code, 400)
-
-    @mock.patch("whodap.client.RDAPClient._get_request")
-    def test_lookup(self, mock_request):
-        self.dns_client.iana_dns_server_map = {'com': 'https://an-rdap-server/'}
-        links = [
-            {
-                'rel': 'self',
-                'href': 'https://an-rdap-server/domain/domain.com',
-                'type': 'application/rdap+json'
-            },
-            {
-                'rel': 'related',
-                'href': 'https://the-authoritative-server/domain/domain.com',
-                'type': 'application/rdap+json'
-            }
-        ]
-        # set up mock request
-        mock_request.return_value = \
-            mock.Mock(status_code=200,
-                      json=mock.Mock(return_value={'links': links}),
-                      read=mock.Mock(return_value=b'{"test": "json"}'))
-        self.dns_client.lookup('domain', 'com')
-        assert mock_request.call_count == 2, f'_aio_get_request call_count {mock_request.call_count} != 2'
-        # reset mock request's return
-        links = [
-            {
-                'rel': 'self',
-                'href': 'https://the-authoritative-server/domain/domain.com',
-                'type': 'application/rdap+json'
-            }
-        ]
-        mock_request.return_value = \
-            mock.Mock(status_code=200,
-                      json=mock.Mock(return_value={'links': links}),
-                      read=mock.Mock(return_value=b'{"test": "json"}'))
-        self.dns_client.lookup('domain', 'com', auth_href='https://the-authoritative-server/domain/domain.com')
-        # should only have made 1 additional request
-        assert mock_request.call_count == 3, f'_aio_get_request call_count {mock_request.call_count} != 3'
-
-    @mock.patch("whodap.client.RDAPClient._aio_get_request")
-    async def test_aio_lookup(self, mock_request):
-        self.dns_client.iana_dns_server_map = {'com': 'https://an-rdap-server/'}
-        links = [
-            {
-                'rel': 'self',
-                'href': 'https://an-rdap-server/domain/domain.com',
-                'type': 'application/rdap+json'
-            },
-            {
-                'rel': 'related',
-                'href': 'https://the-authoritative-server/domain/domain.com',
-                'type': 'application/rdap+json'
-            }
-        ]
-        # set up mock request
-        mock_request.return_value = \
-            mock.CoroutineMock(
+        with pytest.raises(RateLimitError):
+            DNSClient._check_status_code(429)
+        with pytest.raises(NotFoundError):
+            DNSClient._check_status_code(404)
+        with pytest.raises(MalformedQueryError):
+            DNSClient._check_status_code(400)
+
+
+    def test_lookup():
+        with mock.patch("whodap.client.RDAPClient._get_request", return_value=sync_mock_request()) as req:
+            dns_client = DNSClient(None)
+            dns_client.iana_dns_server_map = {"com": "https://an-rdap-server/"}
+            dns_client.lookup("domain", "com")
+            assert (
+                    req.call_count == 2
+            ), f"_aio_get_request call_count {req.call_count} != 2"
+            # reset mock request's return
+            req.return_value = mock.Mock(
                 status_code=200,
-                json=mock.Mock(return_value={'links': links}),
-                read=mock.Mock(return_value=b'{"test": "json"}'))
-        # check it
-        await self.aio_dns_client.aio_lookup('domain', 'com')
-        assert mock_request.call_count == 2, f'_aio_get_request call_count {mock_request.call_count} != 2'
-        links = [
-            {
-                'rel': 'self',
-                'href': 'https://the-authoritative-server/domain/domain.com',
-                'type': 'application/rdap+json'
-            }
-        ]
-        # set up mock request
-        mock_request.return_value = \
-            mock.CoroutineMock(status_code=200,
-                               json=mock.Mock(return_value={'links': links}),
-                               read=mock.Mock(return_value=b'{"test": "json"}'))
-        await self.aio_dns_client.aio_lookup(
-            'domain', 'com', auth_href='https://the-authoritative-server/domain/domain.com')
-        assert mock_request.call_count == 3
-
-    def test_iana_server_map(self):
+                json=mock.Mock(return_value={"links": links_b}),
+                read=mock.Mock(return_value=b'{"test": "json"}'),
+            )
+            dns_client.lookup(
+                "domain",
+                "com",
+                auth_href="https://the-authoritative-server/domain/domain.com",
+            )
+            # should only have made 1 additional request
+            assert (
+                    req.call_count == 3
+            ), f"_aio_get_request call_count {req.call_count} != 3"
+
+
+    @pytest.mark.asyncio
+    async def test_aio_lookup():
+        with mock.patch("whodap.client.RDAPClient._aio_get_request", return_value=async_mock_request()) as req:
+            dns_client = DNSClient(None)
+            dns_client.iana_dns_server_map = {"com": "https://an-rdap-server/"}
+            # check it
+            await dns_client.aio_lookup("domain", "com")
+            assert (
+                    req.call_count == 2
+            ), f"_aio_get_request call_count {req.call_count} != 2"
+            # set up mock request
+            req.return_value = mock.Mock(
+                status_code=200,
+                json=mock.Mock(return_value={"links": links_b}),
+                read=mock.Mock(return_value=b'{"test": "json"}'),
+            )
+            await dns_client.aio_lookup(
+                "domain",
+                "com",
+                auth_href="https://the-authoritative-server/domain/domain.com",
+            )
+            assert req.call_count == 3
+
+
+    def test_iana_server_map():
+        dns_client = DNSClient(None)
         rdap_output = {
             "publication": "2021-05-05",
             "version": "2",
             "services": [
-                [
-                    ["tld1", "tld2", "tld3"],
-                    ["https://api.rdap.somewhere.net/"]
-                ],
-                [
-                    ["tld4"],
-                    ["https://api.rdap.nic/"]
-                ]
-            ]
+                [["tld1", "tld2", "tld3"], ["https://api.rdap.somewhere.net/"]],
+                [["tld4"], ["https://api.rdap.nic/"]],
+            ],
         }
-        self.dns_client._set_iana_info(rdap_output)
-        assert len(self.dns_client.iana_dns_server_map.keys()) == 4
-        assert self.dns_client.publication == "2021-05-05"
-        assert self.dns_client.version == "2"
+        dns_client._set_iana_info(rdap_output)
+        assert len(dns_client.iana_dns_server_map.keys()) == 4
+        assert dns_client.publication == "2021-05-05"
+        assert dns_client.version == "2"
+
 
     @mock.patch("whodap.client.DNSClient._aio_get_request")
-    async def test_aio_get_iana_info(self, mock_request):
+    @pytest.mark.asyncio
+    async def test_aio_get_iana_info(mock_request):
+        dns_client = DNSClient(None)
         mock_request.return_value = mock.Mock(status_code=200, json=mock.Mock())
-        await self.aio_dns_client._aio_get_iana_info()
+        await dns_client._aio_get_iana_info()
         mock_request.assert_called_once()
 
+
     @mock.patch("whodap.client.DNSClient._get_request")
-    def test_load_dns(self, mock_request):
+    def test_load_dns(mock_request):
+        dns_client = DNSClient(None)
         mock_request.return_value = mock.Mock(status_code=200, json=mock.Mock())
-        self.dns_client._get_iana_info()
+        dns_client._get_iana_info()
         mock_request.assert_called_once()
 
-    def test_get_request(self):
+
+    def test_get_request():
+        dns_client = DNSClient(None)
         fake_http_response = "fake-http-response"
         mock_client = mock.Mock(get=mock.Mock(return_value=fake_http_response))
-        self.dns_client.httpx_client = mock_client
-        resp = self.dns_client._get_request("https://www.some-domain.com")
+        dns_client.httpx_client = mock_client
+        resp = dns_client._get_request("https://www.some-domain.com")
         assert resp == fake_http_response, f"{resp} != {fake_http_response}"
 
-    async def test_get_aio_request(self):
+
+    @pytest.mark.asyncio
+    async def test_get_aio_request():
+        dns_client = DNSClient(None)
         fake_http_response = "fake-http-response"
-        mock_client = mock.Mock(get=mock.CoroutineMock(return_value=fake_http_response))
-        self.aio_dns_client.httpx_client = mock_client
-        resp = await self.aio_dns_client._aio_get_request("https://www.some-domain.com")
+        mock_client = mock_http_client()
+        dns_client.httpx_client = mock_client
+        resp = await dns_client._aio_get_request("https://www.some-domain.com")
         assert resp == fake_http_response, f"{resp} != {fake_http_response}"
 
-    async def test_async_context_manager(self):
+
+    @pytest.mark.asyncio
+    async def test_async_context_manager():
         fake_http_response = "fake-http-response"
-        mock_client = mock.Mock(get=mock.CoroutineMock(return_value=fake_http_response),
-                                json=mock.Mock(return_value=fake_http_response))
+        mock_client = mock_http_client()
         async with DNSClient.new_aio_client_context() as aio_dns_client:
             aio_dns_client.httpx_client = mock_client
             resp = await aio_dns_client._aio_get_request("https://www.some-domain.com")
             assert resp == fake_http_response, f"{resp} != {fake_http_response}"
 
-    def test_context_manager(self):
+
+    def test_context_manager():
         fake_http_response = "fake-http-response"
         mock_client = mock.Mock(get=mock.Mock(return_value=fake_http_response))
         with DNSClient.new_client_context() as dns_client:
@@ -183,99 +213,63 @@ def test_context_manager(self):
             resp = dns_client._get_request("https://www.some-domain.com")
             assert resp == fake_http_response, f"{resp} != {fake_http_response}"
 
-    def test__check_next_href(self):
-        current_href = 'https://an-rdap-server/domain/domain.com'
+
+    def test__check_next_href():
+        current_href = "https://an-rdap-server/domain/domain.com"
         links_1 = [
             {
-                'rel': 'self',
-                'href': 'https://an-rdap-server/domain/domain.com',
-                'type': 'application/rdap+json'
+                "rel": "self",
+                "href": "https://an-rdap-server/domain/domain.com",
+                "type": "application/rdap+json",
             },
             {
-                'rel': 'related',
-                'href': 'https://the-authoritative-server/domain/domain.com',
-                'type': 'application/rdap+json'
-            }
+                "rel": "related",
+                "href": "https://the-authoritative-server/domain/domain.com",
+                "type": "application/rdap+json",
+            },
         ]
         links_2 = [
             {
-                'rel': 'self',
-                'href': 'https://an-rdap-server/domain/domain.com',
-                'type': 'application/rdap+json'
+                "rel": "self",
+                "href": "https://an-rdap-server/domain/domain.com",
+                "type": "application/rdap+json",
             },
             {
-                'rel': 'related',
-                'href': 'https://the-authoritative-server',
-                'type': 'text/html'
-            }
+                "rel": "related",
+                "href": "https://the-authoritative-server",
+                "type": "text/html",
+            },
         ]
         links_3 = [
             {
-                'rel': 'self',
-                'href': 'https://an-rdap-server/domain/domain.com',
-                'type': 'application/rdap+json'
+                "rel": "self",
+                "href": "https://an-rdap-server/domain/domain.com",
+                "type": "application/rdap+json",
             }
         ]
         links_4 = [
             {
-                'rel': 'self',
-                'href': 'https://an-rdap-server/domain/domain.com',
-                'type': 'application/rdap+json'
+                "rel": "self",
+                "href": "https://an-rdap-server/domain/domain.com",
+                "type": "application/rdap+json",
             },
             {
-                'rel': 'related',
-                'href': 'https://the-authoritative-server',
-                'type': 'application/rdap+json'
-            }
-
+                "rel": "related",
+                "href": "https://the-authoritative-server",
+                "type": "application/rdap+json",
+            },
         ]
-
         client = DNSClient(None)
         client._target = "domain.com"
         #
         output_1 = client._check_next_href(current_href, links_1)
-        self.assertEqual(output_1, links_1[1].get('href'))
+        assert output_1 == links_1[1].get("href")
         #
         output_2 = client._check_next_href(current_href, links_2)
-        self.assertEqual(output_2, None)
+        assert output_2 is None
         #
         output_3 = client._check_next_href(current_href, links_3)
-        self.assertEqual(output_3, None)
+        assert output_3 is None
         #
         output_4 = client._check_next_href(current_href, links_4)
-        self.assertEqual(output_4, 'https://the-authoritative-server/domain/domain.com')
-
-    def test__check_next_href_with_ip(self):
-        current_href = 'https://an-rdap-server/ip/8.8.8.8'
-        links_1 = [
-            {
-                'rel': 'self',
-                'href': 'https://an-rdap-server/ip/8.8.8.8',
-                'type': 'application/rdap+json'
-            },
-            {
-                'rel': 'related',
-                'href': 'https://the-authoritative-server/domain/8.8.8.255/something',
-                'type': 'application/rdap+json'
-            }
-        ]
-        links_2 = [
-            {
-                'rel': 'self',
-                'href': 'https://an-rdap-server/ip/8.8.8.8',
-                'type': 'application/rdap+json'
-            },
-            {
-                'rel': 'related',
-                'href': 'https://the-authoritative-server/ip/8.8.8.8',
-                'type': 'text/html'
-            }
-        ]
-        client = IPv4Client(None)
-        client._target = ipaddress.IPv4Address('8.8.8.8')
-        #
-        output_1 = client._check_next_href(current_href, links_1)
-        self.assertEqual(output_1, None)
-        #
-        output_2 = client._check_next_href(current_href, links_2)
-        self.assertEqual(output_2, None)
+        assert output_4 == "https://the-authoritative-server/domain/domain.com"
diff --git a/tests/test_package_methods.py b/tests/test_package_methods.py
index 6f3a209..55cb3c8 100644
--- a/tests/test_package_methods.py
+++ b/tests/test_package_methods.py
@@ -1,34 +1,42 @@
-import asynctest
-import asynctest.mock as mock
-
-from whodap import lookup_domain, aio_lookup_domain
-
-
-class TestPackageMethods(asynctest.TestCase):
-    """
-    Tests that the appropriate classes and methods are invoked for each package method.
-    """
-
-    @mock.patch('whodap.DNSClient')
-    def test_lookup_domain(self, mock_dns_client):
-        confirmation_string = 'dns_client_lookup_was_called'
-        mock_dns_client.close = mock.Mock()
-        mock_dns_client.lookup.return_value = confirmation_string
-        mock_dns_client.new_client.return_value = mock_dns_client
-        resp = lookup_domain(domain='some-domain', tld='com')
-        assert resp == confirmation_string, f"{resp} != {confirmation_string}"
-        mock_dns_client.close.assert_called()
-        resp = lookup_domain(domain='some-domain', tld='com')
-        assert resp == confirmation_string, f"{resp} != {confirmation_string}"
-
-    @mock.patch('whodap.DNSClient')
-    async def test_aio_lookup_domain(self, mock_dns_client):
-        confirmation_string = 'dns_client_aio_lookup_was_called'
-        mock_dns_client.aio_close = mock.CoroutineMock()
-        mock_dns_client.aio_lookup = mock.CoroutineMock(return_value=confirmation_string)
-        mock_dns_client.new_aio_client = mock.CoroutineMock(return_value=mock_dns_client)
-        resp = await aio_lookup_domain(domain='some-domain', tld='com')
-        assert resp == confirmation_string, f"{resp} != {confirmation_string}"
-        mock_dns_client.aio_close.assert_called()
-        resp = await aio_lookup_domain(domain='some-domain', tld='com')
-        assert resp == confirmation_string, f"{resp} != {confirmation_string}"
+import asyncio
+import sys
+import unittest.mock as mock
+
+import pytest
+import whodap
+
+
+confirmation_string = "dns_client_lookup_was_called"
+
+
+if sys.version_info >= (3, 8):
+
+    def mock_aio_dns_client():
+        async_mock_client = mock.AsyncMock(
+            name="mock-dns-client",
+            aio_close=mock.AsyncMock(),
+            aio_lookup=mock.AsyncMock(return_value=confirmation_string)
+        )
+        return async_mock_client
+
+
+    def mock_dns_client():
+        mock_client = mock.MagicMock(
+            name="mock-dns-client",
+            close=mock.Mock(),
+            lookup=mock.Mock(return_value=confirmation_string)
+        )
+        return mock_client
+
+
+    def test_lookup_domain():
+        with mock.patch('whodap.DNSClient.new_client', return_value=mock_dns_client()):
+            resp = whodap.lookup_domain(domain="some-domain", tld="com")
+            assert resp == confirmation_string, f"{resp} != {confirmation_string}"
+
+
+    @pytest.mark.asyncio
+    async def test_aio_lookup_domain():
+        with mock.patch('whodap.DNSClient.new_aio_client', return_value=mock_aio_dns_client()):
+            resp = await whodap.aio_lookup_domain(domain="some-domain", tld="com")
+            assert resp == confirmation_string, f"{resp} != {confirmation_string}"
diff --git a/tests/test_response.py b/tests/test_response.py
index df487fc..ad1a8b6 100644
--- a/tests/test_response.py
+++ b/tests/test_response.py
@@ -7,16 +7,15 @@
 
 
 class TestDomainResponse(unittest.TestCase):
-
     def load_file(self, filename: str):
         base_dir = os.path.abspath(os.path.dirname(__file__))
         with open(os.path.join(base_dir, "samples", filename)) as data:
             return data.read()
 
     def setUp(self) -> None:
-        self.address = '123 main street'
-        self.phone = 'tel+18005555555'
-        self.test_filename = 'google.com.json'
+        self.address = "123 main street"
+        self.phone = "tel+18005555555"
+        self.test_filename = "google.com.json"
         self.json_string = self.load_file(self.test_filename)
         self.resp = DomainResponse.from_json(self.json_string)
 
@@ -36,7 +35,11 @@ def test_to_whois_dict(self):
             assert type(k) == WHOISKeys
             if k == WHOISKeys.STATUS or k == WHOISKeys.NAMESERVERS:
                 assert type(v) == list, f"{type(v)} is not list"
-            if k == WHOISKeys.CREATED_DATE or k == WHOISKeys.UPDATED_DATE or k == WHOISKeys.EXPIRES_DATE:
+            if (
+                k == WHOISKeys.CREATED_DATE
+                or k == WHOISKeys.UPDATED_DATE
+                or k == WHOISKeys.EXPIRES_DATE
+            ):
                 assert type(v) == datetime, f"{type(v)} is not datetime"
             if k == WHOISKeys.DNSSEC:
                 assert type(v) == bool, f"{type(v)} is not bool"
@@ -46,21 +49,31 @@ def test_to_whois_json(self):
         whois_json = self.resp.to_whois_json()
         assert type(whois_json) == str
         for k, v in json.loads(whois_json).items():
-            assert k in whois_dict.keys(), f"key {k} from whois_json is not in whois_dict"
+            assert (
+                k in whois_dict.keys()
+            ), f"key {k} from whois_json is not in whois_dict"
 
     def test_convert_self_to_dict(self):
-        json_string = '{"list_key1": [{"inner_dict1": 1}, {"inner_dict2": 2}], "dict_key1": 1}'
+        json_string = (
+            '{"list_key1": [{"inner_dict1": 1}, {"inner_dict2": 2}], "dict_key1": 1}'
+        )
         resp = DomainResponse.from_json(json_string)
         resp_dict = resp._convert_self_to_dict(resp)
         self.assertEqual(list(resp_dict.keys()), list(json.loads(json_string).keys()))
-        self.assertEqual(list(resp_dict.values()), list(json.loads(json_string).values()))
+        self.assertEqual(
+            list(resp_dict.values()), list(json.loads(json_string).values())
+        )
 
     def test_convert_list(self):
-        json_string = '{"list_key1": [{"inner_dict1": 1}, {"inner_dict2": 2}], "dict_key1": 1}'
+        json_string = (
+            '{"list_key1": [{"inner_dict1": 1}, {"inner_dict2": 2}], "dict_key1": 1}'
+        )
         resp = DomainResponse.from_json(json_string)
         resp_dict = resp._convert_self_to_dict(resp)
         self.assertEqual(list(resp_dict.keys()), list(json.loads(json_string).keys()))
-        self.assertEqual(list(resp_dict.values()), list(json.loads(json_string).values()))
+        self.assertEqual(
+            list(resp_dict.values()), list(json.loads(json_string).values())
+        )
 
     def test_convert_dates(self):
         ds_1 = "2015-08-09T18:00:24.000+0000"
@@ -70,27 +83,54 @@ def test_convert_dates(self):
         assert dt_1.year == 2015, f"year {dt_1.year} is not 2015"
         assert dt_1.month == 8, f"month {dt_1.month} is not 8"
         for ds in (ds_1, ds_2, ds_3):
-            assert type(self.resp._convert_date(ds)) == datetime, f"failed to convert to datetime"
+            assert (
+                type(self.resp._convert_date(ds)) == datetime
+            ), f"failed to convert to datetime"
         ds_4 = "unsupported"
-        assert type(self.resp._convert_date(ds_4)) == str, f"unexpected output from _convert_date"
+        assert (
+            type(self.resp._convert_date(ds_4)) == str
+        ), f"unexpected output from _convert_date"
 
     def test_flat_entities(self):
         flattened_entities = self.resp._flat_entities(self.resp.entities)
         for role, role_values in flattened_entities.items():
-            assert role in ('abuse', 'registrant', 'registrar', 'technical', 'billing', 'administrative'), f'{role} not found'
+            assert role in (
+                "abuse",
+                "registrant",
+                "registrar",
+                "technical",
+                "billing",
+                "administrative",
+            ), f"{role} not found"
             for key, value in role_values.items():
-                assert key in ('org', 'abuse', 'address', 'phone', 'name', 'email', 'fax'), f'role_value key {key} not found'
+                assert key in (
+                    "org",
+                    "abuse",
+                    "address",
+                    "phone",
+                    "name",
+                    "email",
+                    "fax",
+                ), f"role_value key {key} not found"
                 assert value is not None
 
     def test_construct_flat_dict(self):
-        flat = {'administrative': {'address': self.address, 'phone': self.phone, 'name': 'test'}}
+        flat = {
+            "administrative": {
+                "address": self.address,
+                "phone": self.phone,
+                "name": "test",
+            }
+        }
         flat_converted = self.resp._construct_flat_dict(flat)
-        num_flat_keys = len(flat_converted.keys())
-        num_whois_keys = len([k for k in dir(WHOISKeys) if not k.startswith('__')])
-        assert flat_converted['admin_address'] == self.address, f"{flat_converted['admin_address']} != {self.address}"
-        assert flat_converted['admin_phone'] == self.phone, f"{flat_converted['admin_phone']} != {self.phone}"
-        assert flat_converted['admin_name'] == 'test', f"{flat_converted['admin_name']} != test"
-        assert num_flat_keys == num_whois_keys - 2, f'{num_flat_keys} != {num_whois_keys}'
+        assert (
+            flat_converted["admin_address"] == self.address
+        ), f"{flat_converted['admin_address']} != {self.address}"
+        assert (
+            flat_converted["admin_phone"] == self.phone
+        ), f"{flat_converted['admin_phone']} != {self.phone}"
+        assert (
+            flat_converted["admin_name"] == "test"
+        ), f"{flat_converted['admin_name']} != test"
         for key, value in flat_converted.items():
             assert type(key) == WHOISKeys
-