Skip to content

Commit 1236eaf

Browse files
committed
refactor: 💡 retire dotenv on esaclient
1 parent 0095c1d commit 1236eaf

File tree

4 files changed

+64
-55
lines changed

4 files changed

+64
-55
lines changed

esa_client.py

Lines changed: 11 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,23 @@
11
import logging
2-
import os
32

43
import requests
5-
from dotenv import load_dotenv
64

7-
load_dotenv()
5+
# from dotenv import load_dotenv
6+
7+
# load_dotenv()
88
logger = logging.getLogger(__name__)
99

1010

1111
class EsaClient:
12-
def __init__(self):
13-
self.token = os.getenv("ESA_TOKEN")
14-
self.team_name = os.getenv("ESA_TEAM_NAME")
12+
def __init__(self, token: str, team_name: str):
13+
self.token = token
14+
self.team_name = team_name
1515

1616
if not self.token:
17-
logger.error("Environment variable ESA_TOKEN is not set.")
17+
logger.error("Token is required but was not provided.")
1818
raise ValueError("ESA_TOKEN is required")
1919
if not self.team_name:
20-
logger.error("Environment variable ESA_TEAM_NAME is not set.")
20+
logger.error("Team name is required but was not provided.")
2121
raise ValueError("ESA_TEAM_NAME is required")
2222

2323
self.base_url = f"https://api.esa.io/v1/teams/{self.team_name}"
@@ -118,6 +118,9 @@ def delete_post(self, post_number: int):
118118

119119
# Example usage (optional, for testing during development)
120120
if __name__ == "__main__":
121+
from dotenv import load_dotenv
122+
123+
load_dotenv()
121124
logging.basicConfig(level=logging.INFO)
122125
try:
123126
client = EsaClient()

main.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@
3232
esa_client = None
3333
else:
3434
try:
35-
esa_client = EsaClient()
35+
esa_client = EsaClient(token=esa_token, team_name=esa_team_name)
3636
logger.info("EsaClient initialized successfully.")
3737
except ValueError as e: # Catch potential ValueError from EsaClient init
3838
logger.error(f"Failed to initialize EsaClient: {e}")

tests/integration/test_esa_client_integration.py

Lines changed: 39 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import os
12
import random
23
import time
34

@@ -11,18 +12,32 @@
1112
load_dotenv()
1213

1314

15+
@pytest.fixture(scope="module")
16+
def integration_client():
17+
token = os.getenv("ESA_TOKEN")
18+
team_name = os.getenv("ESA_TEAM_NAME")
19+
if not token or not team_name:
20+
pytest.skip("ESA_TOKEN or ESA_TEAM_NAME not set for integration tests. Skipping integration tests.")
21+
try:
22+
client = EsaClient(token=token, team_name=team_name)
23+
return client
24+
except ValueError as e:
25+
pytest.fail(f"Failed to initialize EsaClient for integration tests: {e}. Is .env configured correctly?")
26+
except Exception as e:
27+
pytest.fail(f"An unexpected error occurred during EsaClient initialization for integration tests: {e}")
28+
29+
1430
# Note: These tests require a valid .env file with ESA_TOKEN and ESA_TEAM_NAME
1531
# and will make actual API calls to esa.io.
1632
# They might be skipped by default unless explicitly run.
1733

1834

1935
@pytest.mark.integration
20-
def test_get_user_integration():
36+
def test_get_user_integration(integration_client):
2137
"Test get_user against the actual esa.io API."
38+
client = integration_client
2239
try:
23-
# Create a real client instance (loads .env)
24-
client = EsaClient()
25-
print(f"\nRunning integration test for team: {client.team_name}")
40+
print(f"\nRunning get_user_integration test for team: {client.team_name}")
2641
user_data = client.get_user()
2742
print(f"Received user data: {user_data}")
2843

@@ -32,19 +47,17 @@ def test_get_user_integration():
3247
assert "email" in user_data
3348
print("Integration test passed.")
3449

35-
except ValueError as e:
36-
pytest.fail(f"Integration test setup failed: {e}. Is .env configured correctly?")
3750
except requests.exceptions.RequestException as e:
3851
pytest.fail(f"Integration test API call failed: {e}")
3952
except Exception as e:
4053
pytest.fail(f"Integration test unexpected error: {e}")
4154

4255

4356
@pytest.mark.integration
44-
def test_get_posts_integration():
57+
def test_get_posts_integration(integration_client):
4558
"Test get_posts against the actual esa.io API (no params)."
59+
client = integration_client
4660
try:
47-
client = EsaClient()
4861
print(f"\nRunning get_posts integration test for team: {client.team_name}")
4962
posts_data = client.get_posts()
5063
posts_list = posts_data.get("posts", [])
@@ -79,12 +92,12 @@ def test_get_posts_integration():
7992

8093

8194
@pytest.mark.integration
82-
def test_get_posts_pagination_integration():
95+
def test_get_posts_pagination_integration(integration_client):
8396
"Test get_posts pagination against the actual esa.io API."
97+
client = integration_client
8498
test_page = 2
8599
test_per_page = 5
86100
try:
87-
client = EsaClient()
88101
print(f"\nRunning get_posts pagination integration test (page={test_page}, per_page={test_per_page})")
89102
posts_data = client.get_posts(page=test_page, per_page=test_per_page)
90103
posts_list = posts_data.get("posts", [])
@@ -122,13 +135,13 @@ def test_get_posts_pagination_integration():
122135

123136

124137
@pytest.mark.integration
125-
def test_get_post_integration():
138+
def test_get_post_integration(integration_client):
126139
"Test get_post against the actual esa.io API (existing post)."
140+
client = integration_client
127141
# Note: Assumes post number 1 exists in the test team.
128142
# Adjust post_number if necessary for your test environment.
129143
test_post_number = 1
130144
try:
131-
client = EsaClient()
132145
print(f"\nRunning get_post integration test for post #{test_post_number}")
133146
post_data = client.get_post(post_number=test_post_number)
134147
print(f"Received post title: {post_data.get('name')}")
@@ -153,12 +166,12 @@ def test_get_post_integration():
153166

154167

155168
@pytest.mark.integration
156-
def test_get_post_not_found_integration():
169+
def test_get_post_not_found_integration(integration_client):
157170
"Test get_post against the actual esa.io API (non-existent post)."
171+
client = integration_client
158172
# Use a post number that is guaranteed not to exist (e.g., 0 or a very large number)
159173
test_post_number = 0
160174
try:
161-
client = EsaClient()
162175
print(f"\nRunning get_post integration test for non-existent post #{test_post_number}")
163176
with pytest.raises(requests.exceptions.HTTPError) as exc_info:
164177
client.get_post(post_number=test_post_number)
@@ -180,9 +193,9 @@ def test_get_post_not_found_integration():
180193

181194

182195
@pytest.mark.integration
183-
def test_create_post_integration():
196+
def test_create_post_integration(integration_client):
184197
"""Test create_post and verify the created post."""
185-
client = EsaClient()
198+
client = integration_client
186199
unique_name = f"Test Post - {int(time.time())}"
187200
post_payload = {
188201
"name": unique_name,
@@ -240,9 +253,9 @@ def test_create_post_integration():
240253

241254

242255
@pytest.mark.integration
243-
def test_delete_post_integration():
256+
def test_delete_post_integration(integration_client):
244257
"""Test create_post, then delete_post, and verify deletion."""
245-
client = EsaClient()
258+
client = integration_client
246259
unique_name = f"Test Post for Deletion - {int(time.time())}"
247260
post_payload = {
248261
"name": unique_name,
@@ -284,9 +297,9 @@ def test_delete_post_integration():
284297

285298

286299
@pytest.mark.integration
287-
def test_delete_post_non_existent_integration():
300+
def test_delete_post_non_existent_integration(integration_client):
288301
"""Test delete_post with a non-existent post_number."""
289-
client = EsaClient()
302+
client = integration_client
290303
non_existent_post_number = 0
291304
with pytest.raises(requests.exceptions.HTTPError) as excinfo:
292305
client.delete_post(non_existent_post_number)
@@ -295,9 +308,9 @@ def test_delete_post_non_existent_integration():
295308

296309

297310
@pytest.mark.integration
298-
def test_update_post_integration():
311+
def test_update_post_integration(integration_client):
299312
"""Test creating, updating, and verifying a post."""
300-
client = EsaClient()
313+
client = integration_client
301314
original_name = f"Original Post Title - {int(time.time())}"
302315
updated_name = f"Updated Post Title - {int(time.time())}"
303316
post_payload = {
@@ -354,9 +367,9 @@ def test_update_post_integration():
354367

355368

356369
@pytest.mark.integration
357-
def test_update_post_not_found_integration():
370+
def test_update_post_not_found_integration(integration_client):
358371
"""Test updating a non-existent post."""
359-
client = EsaClient()
372+
client = integration_client
360373
non_existent_post_number = 0 # A post number that is guaranteed not to exist
361374
update_payload = {"name": "Attempt to update non-existent post", "body_md": "This should not succeed."}
362375

@@ -368,9 +381,9 @@ def test_update_post_not_found_integration():
368381

369382

370383
@pytest.mark.integration
371-
def test_create_post_with_all_fields_integration():
384+
def test_create_post_with_all_fields_integration(integration_client):
372385
"""Test create_post with all optional fields and verify them."""
373-
client = EsaClient()
386+
client = integration_client
374387
unique_suffix = int(time.time())
375388
post_name = f"Test All Fields - {unique_suffix}"
376389
post_body = f"Body for all fields test created at {unique_suffix}."

tests/test_esa_client.py

Lines changed: 13 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -7,16 +7,9 @@
77

88

99
@pytest.fixture
10-
def mock_env(monkeypatch):
11-
"Set up environment variables for testing."
12-
monkeypatch.setenv("ESA_TOKEN", "test_token")
13-
monkeypatch.setenv("ESA_TEAM_NAME", "test_team")
14-
15-
16-
@pytest.fixture
17-
def client(mock_env):
18-
"Return an instance of EsaClient with mocked env vars."
19-
return EsaClient()
10+
def client():
11+
"Return an instance of EsaClient with specified token and team_name."
12+
return EsaClient(token="test_token", team_name="test_team")
2013

2114

2215
def test_esa_client_initialization(client):
@@ -27,20 +20,20 @@ def test_esa_client_initialization(client):
2720
assert client.session.headers["Authorization"] == f"Bearer {client.token}"
2821

2922

30-
def test_esa_client_initialization_missing_token(monkeypatch):
31-
"Test ValueError is raised if ESA_TOKEN is missing."
32-
monkeypatch.delenv("ESA_TOKEN", raising=False) # Ensure it's removed if exists
33-
monkeypatch.setenv("ESA_TEAM_NAME", "test_team")
23+
def test_esa_client_initialization_missing_token():
24+
"Test ValueError is raised if token is missing or invalid."
3425
with pytest.raises(ValueError, match="ESA_TOKEN is required"):
35-
EsaClient()
26+
EsaClient(token=None, team_name="test_team")
27+
with pytest.raises(ValueError, match="ESA_TOKEN is required"):
28+
EsaClient(token="", team_name="test_team")
3629

3730

38-
def test_esa_client_initialization_missing_team_name(monkeypatch):
39-
"Test ValueError is raised if ESA_TEAM_NAME is missing."
40-
monkeypatch.setenv("ESA_TOKEN", "test_token")
41-
monkeypatch.delenv("ESA_TEAM_NAME", raising=False) # Ensure it's removed if exists
31+
def test_esa_client_initialization_missing_team_name():
32+
"Test ValueError is raised if team_name is missing or invalid."
33+
with pytest.raises(ValueError, match="ESA_TEAM_NAME is required"):
34+
EsaClient(token="test_token", team_name=None)
4235
with pytest.raises(ValueError, match="ESA_TEAM_NAME is required"):
43-
EsaClient()
36+
EsaClient(token="test_token", team_name="")
4437

4538

4639
@patch("esa_client.requests.Session.request")

0 commit comments

Comments
 (0)