Spaces:
Sleeping
Sleeping
Added mocking to test to avoid API calls where possible
Browse files- functions/writer_agent.py +3 -2
- tests/test_gradio.py +218 -32
- tests/test_resumate.py +0 -3
functions/writer_agent.py
CHANGED
@@ -187,7 +187,8 @@ def _write_projects_section(project_repos: list, job_call: dict) -> str:
|
|
187 |
},
|
188 |
{
|
189 |
'role': 'user',
|
190 |
-
'content': f'JOB CALL\n{json.dumps(job_call)}\n\
|
|
|
191 |
}
|
192 |
]
|
193 |
|
@@ -206,4 +207,4 @@ def _write_projects_section(project_repos: list, job_call: dict) -> str:
|
|
206 |
if response is not None:
|
207 |
response = response.choices[0].message.content
|
208 |
|
209 |
-
return response
|
|
|
187 |
},
|
188 |
{
|
189 |
'role': 'user',
|
190 |
+
'content': (f'JOB CALL\n{json.dumps(job_call)}\n\n' +
|
191 |
+
f'REPOSITORIES\n{json.dumps(project_repos)}')
|
192 |
}
|
193 |
]
|
194 |
|
|
|
207 |
if response is not None:
|
208 |
response = response.choices[0].message.content
|
209 |
|
210 |
+
return response
|
tests/test_gradio.py
CHANGED
@@ -22,24 +22,45 @@ class TestProcessInputs(unittest.TestCase):
|
|
22 |
self.skipTest(f"Test PDF file not found: {test_pdf_path}")
|
23 |
|
24 |
with patch('functions.gradio.extract_text') as mock_extract, \
|
25 |
-
patch('functions.gradio.get_github_repositories') as mock_github
|
|
|
|
|
26 |
|
27 |
mock_extract.return_value = {"test": "data"}
|
28 |
mock_github.return_value = [{"name": "test-repo"}]
|
|
|
|
|
29 |
|
30 |
result = gradio.process_inputs(
|
31 |
linkedin_pdf_path=str(test_pdf_path),
|
32 |
github_username="testuser",
|
33 |
-
job_post_text="Software engineer position"
|
34 |
-
user_instructions="Custom instructions"
|
35 |
)
|
36 |
|
37 |
-
#
|
38 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
39 |
|
|
|
|
|
40 |
@patch('functions.gradio.extract_text')
|
41 |
@patch('functions.gradio.get_github_repositories')
|
42 |
-
def test_process_inputs_with_pdf_path_mocked(
|
|
|
|
|
|
|
|
|
|
|
|
|
43 |
"""Test process_inputs with a PDF file path (mocked for controlled testing)."""
|
44 |
|
45 |
# Mock successful LinkedIn text extraction
|
@@ -49,12 +70,16 @@ class TestProcessInputs(unittest.TestCase):
|
|
49 |
"experience": "Software Engineer at Company"
|
50 |
}
|
51 |
mock_github.return_value = [{"name": "test-repo"}]
|
|
|
|
|
|
|
|
|
|
|
52 |
|
53 |
result = gradio.process_inputs(
|
54 |
linkedin_pdf_path="/path/to/resume.pdf",
|
55 |
github_username="testuser",
|
56 |
-
job_post_text="Software engineer position"
|
57 |
-
user_instructions="Custom instructions"
|
58 |
)
|
59 |
|
60 |
# Verify extract_text was called with the correct path
|
@@ -63,125 +88,287 @@ class TestProcessInputs(unittest.TestCase):
|
|
63 |
# Verify get_github_repositories was called with username
|
64 |
mock_github.assert_called_once_with("testuser")
|
65 |
|
66 |
-
#
|
67 |
-
|
|
|
|
|
|
|
68 |
|
|
|
|
|
|
|
|
|
|
|
69 |
@patch('functions.gradio.extract_text')
|
70 |
@patch('functions.gradio.get_github_repositories')
|
71 |
-
def test_process_inputs_extraction_failure(
|
|
|
|
|
|
|
|
|
|
|
72 |
"""Test process_inputs when LinkedIn extraction fails."""
|
73 |
|
74 |
# Mock failed LinkedIn text extraction
|
75 |
mock_extract.return_value = None
|
76 |
mock_github.return_value = None
|
|
|
77 |
|
78 |
result = gradio.process_inputs(
|
79 |
linkedin_pdf_path="/path/to/resume.pdf",
|
80 |
github_username="testuser",
|
81 |
-
job_post_text="Software engineer position"
|
82 |
-
user_instructions="Custom instructions"
|
83 |
)
|
84 |
|
85 |
# Verify extract_text was called
|
86 |
mock_extract.assert_called_once_with("/path/to/resume.pdf")
|
87 |
mock_github.assert_called_once_with("testuser")
|
|
|
|
|
|
|
|
|
88 |
|
89 |
-
# Function
|
90 |
self.assertEqual(result, "")
|
91 |
|
|
|
|
|
92 |
@patch('functions.gradio.extract_text')
|
93 |
@patch('functions.gradio.get_github_repositories')
|
94 |
-
def test_process_inputs_no_pdf_path(
|
|
|
|
|
|
|
|
|
|
|
|
|
95 |
"""Test process_inputs with no PDF path provided."""
|
|
|
96 |
mock_extract.return_value = None
|
97 |
mock_github.return_value = []
|
|
|
98 |
|
99 |
result = gradio.process_inputs(
|
100 |
linkedin_pdf_path=None,
|
101 |
github_username="testuser",
|
102 |
-
job_post_text="Software engineer position"
|
103 |
-
user_instructions="Custom instructions"
|
104 |
)
|
105 |
|
106 |
# extract_text should be called with None
|
107 |
mock_extract.assert_called_once_with(None)
|
108 |
mock_github.assert_called_once_with("testuser")
|
|
|
109 |
|
110 |
-
#
|
|
|
|
|
|
|
111 |
self.assertEqual(result, "")
|
112 |
|
|
|
|
|
113 |
@patch('functions.gradio.extract_text')
|
114 |
@patch('functions.gradio.get_github_repositories')
|
115 |
-
def test_process_inputs_with_long_job_post(
|
|
|
|
|
|
|
|
|
|
|
|
|
116 |
"""Test process_inputs with a long job post text (for logging truncation)."""
|
117 |
|
118 |
mock_extract.return_value = {
|
119 |
"summary": "Test summary"
|
120 |
}
|
121 |
mock_github.return_value = []
|
|
|
122 |
|
123 |
long_job_post = "This is a very long job posting " * 50 # Make it longer than 100 chars
|
124 |
|
125 |
result = gradio.process_inputs(
|
126 |
linkedin_pdf_path="/path/to/resume.pdf",
|
127 |
github_username="testuser",
|
128 |
-
job_post_text=long_job_post
|
129 |
-
user_instructions="Custom instructions"
|
130 |
)
|
131 |
|
132 |
# Verify extract_text was called
|
133 |
mock_extract.assert_called_once_with("/path/to/resume.pdf")
|
134 |
mock_github.assert_called_once_with("testuser")
|
|
|
|
|
|
|
|
|
135 |
|
136 |
-
# Function
|
137 |
self.assertEqual(result, "")
|
138 |
|
|
|
|
|
139 |
@patch('functions.gradio.extract_text')
|
140 |
@patch('functions.gradio.get_github_repositories')
|
141 |
-
def test_process_inputs_github_username_whitespace(
|
|
|
|
|
|
|
|
|
|
|
|
|
142 |
"""Test that github_username is properly stripped of whitespace."""
|
143 |
|
144 |
mock_extract.return_value = None
|
145 |
mock_github.return_value = []
|
|
|
146 |
|
147 |
result = gradio.process_inputs(
|
148 |
linkedin_pdf_path=None,
|
149 |
github_username=" testuser ",
|
150 |
-
job_post_text=""
|
151 |
-
user_instructions=""
|
152 |
)
|
153 |
|
154 |
# Verify get_github_repositories was called with stripped username
|
155 |
mock_github.assert_called_once_with("testuser")
|
|
|
156 |
self.assertEqual(result, "")
|
157 |
|
|
|
|
|
158 |
@patch('functions.gradio.extract_text')
|
159 |
@patch('functions.gradio.get_github_repositories')
|
160 |
@patch('logging.getLogger')
|
161 |
-
def test_logging_calls(
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
162 |
"""Test that appropriate logging calls are made."""
|
163 |
|
164 |
mock_logger = mock_get_logger.return_value
|
165 |
mock_extract.return_value = {"test": "data"}
|
166 |
mock_github.return_value = [{"name": "repo"}]
|
|
|
|
|
167 |
|
168 |
-
gradio.process_inputs(
|
169 |
linkedin_pdf_path="/path/to/resume.pdf",
|
170 |
github_username="testuser",
|
171 |
-
job_post_text="Job description here"
|
172 |
-
user_instructions="Custom instructions"
|
173 |
)
|
174 |
|
175 |
# Verify logging calls were made
|
176 |
mock_logger.info.assert_called()
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
177 |
|
|
|
|
|
178 |
@patch('functions.gradio.extract_text')
|
179 |
@patch('functions.gradio.get_github_repositories')
|
180 |
-
def test_process_inputs_none_github_username(
|
|
|
|
|
|
|
|
|
|
|
|
|
181 |
"""Test process_inputs with None github_username (should handle gracefully)."""
|
182 |
|
183 |
mock_extract.return_value = None
|
184 |
mock_github.return_value = None
|
|
|
185 |
|
186 |
# This should raise a TypeError due to the bug in gradio.py
|
187 |
# where it tries to slice job_post_text[:100] when job_post_text is None
|
@@ -189,8 +376,7 @@ class TestProcessInputs(unittest.TestCase):
|
|
189 |
gradio.process_inputs(
|
190 |
linkedin_pdf_path=None,
|
191 |
github_username=None,
|
192 |
-
job_post_text=None
|
193 |
-
user_instructions=None
|
194 |
)
|
195 |
|
196 |
|
|
|
22 |
self.skipTest(f"Test PDF file not found: {test_pdf_path}")
|
23 |
|
24 |
with patch('functions.gradio.extract_text') as mock_extract, \
|
25 |
+
patch('functions.gradio.get_github_repositories') as mock_github, \
|
26 |
+
patch('functions.gradio.summarize_job_call') as mock_job_call, \
|
27 |
+
patch('functions.gradio.write_resume') as mock_write_resume:
|
28 |
|
29 |
mock_extract.return_value = {"test": "data"}
|
30 |
mock_github.return_value = [{"name": "test-repo"}]
|
31 |
+
mock_job_call.return_value = {"title": "Software Engineer", "requirements": ["Python"]}
|
32 |
+
mock_write_resume.return_value = "# Generated Resume\n\nTest resume content"
|
33 |
|
34 |
result = gradio.process_inputs(
|
35 |
linkedin_pdf_path=str(test_pdf_path),
|
36 |
github_username="testuser",
|
37 |
+
job_post_text="Software engineer position"
|
|
|
38 |
)
|
39 |
|
40 |
+
# Verify all functions were called
|
41 |
+
mock_extract.assert_called_once_with(str(test_pdf_path))
|
42 |
+
mock_github.assert_called_once_with("testuser")
|
43 |
+
mock_job_call.assert_called_once_with("Software engineer position")
|
44 |
+
mock_write_resume.assert_called_once_with(
|
45 |
+
{"test": "data"},
|
46 |
+
[{"name": "test-repo"}],
|
47 |
+
{"title": "Software Engineer", "requirements": ["Python"]}
|
48 |
+
)
|
49 |
+
|
50 |
+
# Function should return the generated resume
|
51 |
+
self.assertEqual(result, "# Generated Resume\n\nTest resume content")
|
52 |
|
53 |
+
@patch('functions.gradio.write_resume')
|
54 |
+
@patch('functions.gradio.summarize_job_call')
|
55 |
@patch('functions.gradio.extract_text')
|
56 |
@patch('functions.gradio.get_github_repositories')
|
57 |
+
def test_process_inputs_with_pdf_path_mocked(
|
58 |
+
self,
|
59 |
+
mock_github,
|
60 |
+
mock_extract,
|
61 |
+
mock_job_call,
|
62 |
+
mock_write_resume
|
63 |
+
):
|
64 |
"""Test process_inputs with a PDF file path (mocked for controlled testing)."""
|
65 |
|
66 |
# Mock successful LinkedIn text extraction
|
|
|
70 |
"experience": "Software Engineer at Company"
|
71 |
}
|
72 |
mock_github.return_value = [{"name": "test-repo"}]
|
73 |
+
mock_job_call.return_value = {
|
74 |
+
"title": "Software Engineer",
|
75 |
+
"requirements": ["Python", "JavaScript"]
|
76 |
+
}
|
77 |
+
mock_write_resume.return_value = "# John Doe\n\n## Summary\nExperienced software engineer"
|
78 |
|
79 |
result = gradio.process_inputs(
|
80 |
linkedin_pdf_path="/path/to/resume.pdf",
|
81 |
github_username="testuser",
|
82 |
+
job_post_text="Software engineer position"
|
|
|
83 |
)
|
84 |
|
85 |
# Verify extract_text was called with the correct path
|
|
|
88 |
# Verify get_github_repositories was called with username
|
89 |
mock_github.assert_called_once_with("testuser")
|
90 |
|
91 |
+
# Verify job post was processed
|
92 |
+
mock_job_call.assert_called_once_with("Software engineer position")
|
93 |
+
|
94 |
+
# Verify resume generation was called with correct arguments
|
95 |
+
mock_write_resume.assert_called_once()
|
96 |
|
97 |
+
# Function should return the generated resume content
|
98 |
+
self.assertEqual(result, "# John Doe\n\n## Summary\nExperienced software engineer")
|
99 |
+
|
100 |
+
@patch('functions.gradio.write_resume')
|
101 |
+
@patch('functions.gradio.summarize_job_call')
|
102 |
@patch('functions.gradio.extract_text')
|
103 |
@patch('functions.gradio.get_github_repositories')
|
104 |
+
def test_process_inputs_extraction_failure(
|
105 |
+
self, mock_github,
|
106 |
+
mock_extract,
|
107 |
+
mock_job_call,
|
108 |
+
mock_write_resume
|
109 |
+
):
|
110 |
"""Test process_inputs when LinkedIn extraction fails."""
|
111 |
|
112 |
# Mock failed LinkedIn text extraction
|
113 |
mock_extract.return_value = None
|
114 |
mock_github.return_value = None
|
115 |
+
mock_job_call.return_value = None
|
116 |
|
117 |
result = gradio.process_inputs(
|
118 |
linkedin_pdf_path="/path/to/resume.pdf",
|
119 |
github_username="testuser",
|
120 |
+
job_post_text="Software engineer position"
|
|
|
121 |
)
|
122 |
|
123 |
# Verify extract_text was called
|
124 |
mock_extract.assert_called_once_with("/path/to/resume.pdf")
|
125 |
mock_github.assert_called_once_with("testuser")
|
126 |
+
mock_job_call.assert_called_once_with("Software engineer position")
|
127 |
+
|
128 |
+
# write_resume should NOT be called when data is missing
|
129 |
+
mock_write_resume.assert_not_called()
|
130 |
|
131 |
+
# Function should return empty string when processing fails
|
132 |
self.assertEqual(result, "")
|
133 |
|
134 |
+
@patch('functions.gradio.write_resume')
|
135 |
+
@patch('functions.gradio.summarize_job_call')
|
136 |
@patch('functions.gradio.extract_text')
|
137 |
@patch('functions.gradio.get_github_repositories')
|
138 |
+
def test_process_inputs_no_pdf_path(
|
139 |
+
self,
|
140 |
+
mock_github,
|
141 |
+
mock_extract,
|
142 |
+
mock_job_call,
|
143 |
+
mock_write_resume
|
144 |
+
):
|
145 |
"""Test process_inputs with no PDF path provided."""
|
146 |
+
|
147 |
mock_extract.return_value = None
|
148 |
mock_github.return_value = []
|
149 |
+
mock_job_call.return_value = {"title": "Software Engineer"}
|
150 |
|
151 |
result = gradio.process_inputs(
|
152 |
linkedin_pdf_path=None,
|
153 |
github_username="testuser",
|
154 |
+
job_post_text="Software engineer position"
|
|
|
155 |
)
|
156 |
|
157 |
# extract_text should be called with None
|
158 |
mock_extract.assert_called_once_with(None)
|
159 |
mock_github.assert_called_once_with("testuser")
|
160 |
+
mock_job_call.assert_called_once_with("Software engineer position")
|
161 |
|
162 |
+
# write_resume should NOT be called when LinkedIn data is missing
|
163 |
+
mock_write_resume.assert_not_called()
|
164 |
+
|
165 |
+
# Function should return empty string when data is insufficient
|
166 |
self.assertEqual(result, "")
|
167 |
|
168 |
+
@patch('functions.gradio.write_resume')
|
169 |
+
@patch('functions.gradio.summarize_job_call')
|
170 |
@patch('functions.gradio.extract_text')
|
171 |
@patch('functions.gradio.get_github_repositories')
|
172 |
+
def test_process_inputs_with_long_job_post(
|
173 |
+
self,
|
174 |
+
mock_github,
|
175 |
+
mock_extract,
|
176 |
+
mock_job_call,
|
177 |
+
mock_write_resume
|
178 |
+
):
|
179 |
"""Test process_inputs with a long job post text (for logging truncation)."""
|
180 |
|
181 |
mock_extract.return_value = {
|
182 |
"summary": "Test summary"
|
183 |
}
|
184 |
mock_github.return_value = []
|
185 |
+
mock_job_call.return_value = {"title": "Software Engineer", "requirements": ["Python"]}
|
186 |
|
187 |
long_job_post = "This is a very long job posting " * 50 # Make it longer than 100 chars
|
188 |
|
189 |
result = gradio.process_inputs(
|
190 |
linkedin_pdf_path="/path/to/resume.pdf",
|
191 |
github_username="testuser",
|
192 |
+
job_post_text=long_job_post
|
|
|
193 |
)
|
194 |
|
195 |
# Verify extract_text was called
|
196 |
mock_extract.assert_called_once_with("/path/to/resume.pdf")
|
197 |
mock_github.assert_called_once_with("testuser")
|
198 |
+
mock_job_call.assert_called_once_with(long_job_post.strip())
|
199 |
+
|
200 |
+
# write_resume should NOT be called when GitHub repos are empty
|
201 |
+
mock_write_resume.assert_not_called()
|
202 |
|
203 |
+
# Function should return empty string when GitHub data is missing
|
204 |
self.assertEqual(result, "")
|
205 |
|
206 |
+
@patch('functions.gradio.write_resume')
|
207 |
+
@patch('functions.gradio.summarize_job_call')
|
208 |
@patch('functions.gradio.extract_text')
|
209 |
@patch('functions.gradio.get_github_repositories')
|
210 |
+
def test_process_inputs_github_username_whitespace(
|
211 |
+
self,
|
212 |
+
mock_github,
|
213 |
+
mock_extract,
|
214 |
+
mock_job_call,
|
215 |
+
mock_write_resume
|
216 |
+
):
|
217 |
"""Test that github_username is properly stripped of whitespace."""
|
218 |
|
219 |
mock_extract.return_value = None
|
220 |
mock_github.return_value = []
|
221 |
+
mock_job_call.return_value = {"title": "Engineer"}
|
222 |
|
223 |
result = gradio.process_inputs(
|
224 |
linkedin_pdf_path=None,
|
225 |
github_username=" testuser ",
|
226 |
+
job_post_text=""
|
|
|
227 |
)
|
228 |
|
229 |
# Verify get_github_repositories was called with stripped username
|
230 |
mock_github.assert_called_once_with("testuser")
|
231 |
+
mock_write_resume.assert_not_called()
|
232 |
self.assertEqual(result, "")
|
233 |
|
234 |
+
@patch('functions.gradio.write_resume')
|
235 |
+
@patch('functions.gradio.summarize_job_call')
|
236 |
@patch('functions.gradio.extract_text')
|
237 |
@patch('functions.gradio.get_github_repositories')
|
238 |
@patch('logging.getLogger')
|
239 |
+
def test_logging_calls(
|
240 |
+
self,
|
241 |
+
mock_get_logger,
|
242 |
+
mock_github,
|
243 |
+
mock_extract,
|
244 |
+
mock_job_call,
|
245 |
+
mock_write_resume
|
246 |
+
):
|
247 |
"""Test that appropriate logging calls are made."""
|
248 |
|
249 |
mock_logger = mock_get_logger.return_value
|
250 |
mock_extract.return_value = {"test": "data"}
|
251 |
mock_github.return_value = [{"name": "repo"}]
|
252 |
+
mock_job_call.return_value = {"title": "Engineer"}
|
253 |
+
mock_write_resume.return_value = "# Resume Content"
|
254 |
|
255 |
+
result = gradio.process_inputs(
|
256 |
linkedin_pdf_path="/path/to/resume.pdf",
|
257 |
github_username="testuser",
|
258 |
+
job_post_text="Job description here"
|
|
|
259 |
)
|
260 |
|
261 |
# Verify logging calls were made
|
262 |
mock_logger.info.assert_called()
|
263 |
+
# Verify resume was generated successfully
|
264 |
+
self.assertEqual(result, "# Resume Content")
|
265 |
+
|
266 |
+
@patch('functions.gradio.write_resume')
|
267 |
+
@patch('functions.gradio.summarize_job_call')
|
268 |
+
@patch('functions.gradio.extract_text')
|
269 |
+
@patch('functions.gradio.get_github_repositories')
|
270 |
+
def test_process_inputs_write_resume_exception(
|
271 |
+
self,
|
272 |
+
mock_github,
|
273 |
+
mock_extract,
|
274 |
+
mock_job_call,
|
275 |
+
mock_write_resume
|
276 |
+
):
|
277 |
+
"""Test process_inputs when write_resume raises an exception."""
|
278 |
+
|
279 |
+
mock_extract.return_value = {"test": "data"}
|
280 |
+
mock_github.return_value = [{"name": "repo"}]
|
281 |
+
mock_job_call.return_value = {"title": "Engineer"}
|
282 |
+
mock_write_resume.side_effect = Exception("API Error")
|
283 |
+
|
284 |
+
result = gradio.process_inputs(
|
285 |
+
linkedin_pdf_path="/path/to/resume.pdf",
|
286 |
+
github_username="testuser",
|
287 |
+
job_post_text="Job description here"
|
288 |
+
)
|
289 |
+
|
290 |
+
# Verify all functions were called
|
291 |
+
mock_extract.assert_called_once_with("/path/to/resume.pdf")
|
292 |
+
mock_github.assert_called_once_with("testuser")
|
293 |
+
mock_job_call.assert_called_once_with("Job description here")
|
294 |
+
mock_write_resume.assert_called_once()
|
295 |
+
|
296 |
+
# Function should return empty string when write_resume fails
|
297 |
+
self.assertEqual(result, "")
|
298 |
+
|
299 |
+
@patch('functions.gradio.write_resume')
|
300 |
+
@patch('functions.gradio.summarize_job_call')
|
301 |
+
@patch('functions.gradio.extract_text')
|
302 |
+
@patch('functions.gradio.get_github_repositories')
|
303 |
+
def test_process_inputs_complete_success_flow(
|
304 |
+
self,
|
305 |
+
mock_github,
|
306 |
+
mock_extract,
|
307 |
+
mock_job_call,
|
308 |
+
mock_write_resume
|
309 |
+
):
|
310 |
+
"""Test the complete successful flow with all components working."""
|
311 |
+
|
312 |
+
# Mock all successful responses
|
313 |
+
linkedin_data = {
|
314 |
+
"contact_info": "Jane Doe, [email protected]",
|
315 |
+
"summary": "Senior Python Developer",
|
316 |
+
"experience": "5 years experience in Python development"
|
317 |
+
}
|
318 |
+
github_repos = [
|
319 |
+
{"name": "awesome-python-app", "description": "A Python web application"},
|
320 |
+
{"name": "data-analysis-tool", "description": "Data analysis with pandas"}
|
321 |
+
]
|
322 |
+
job_data = {
|
323 |
+
"title": "Senior Python Developer",
|
324 |
+
"requirements": ["Python", "Django", "PostgreSQL"],
|
325 |
+
"company": "Tech Corp"
|
326 |
+
}
|
327 |
+
resume_content = (
|
328 |
+
"# Jane Doe\n\n## Experience\n"
|
329 |
+
"Senior Python Developer with 5 years experience..."
|
330 |
+
)
|
331 |
+
|
332 |
+
mock_extract.return_value = linkedin_data
|
333 |
+
mock_github.return_value = github_repos
|
334 |
+
mock_job_call.return_value = job_data
|
335 |
+
mock_write_resume.return_value = resume_content
|
336 |
+
|
337 |
+
result = gradio.process_inputs(
|
338 |
+
linkedin_pdf_path="/path/to/jane_resume.pdf",
|
339 |
+
github_username="jane_dev",
|
340 |
+
job_post_text="We are looking for a Senior Python Developer with Django experience..."
|
341 |
+
)
|
342 |
+
|
343 |
+
# Verify all functions were called with correct arguments
|
344 |
+
mock_extract.assert_called_once_with("/path/to/jane_resume.pdf")
|
345 |
+
mock_github.assert_called_once_with("jane_dev")
|
346 |
+
mock_job_call.assert_called_once_with(
|
347 |
+
"We are looking for a Senior Python Developer with Django experience..."
|
348 |
+
)
|
349 |
+
mock_write_resume.assert_called_once_with(linkedin_data, github_repos, job_data)
|
350 |
+
|
351 |
+
# Verify the complete resume is returned
|
352 |
+
self.assertEqual(result, resume_content)
|
353 |
+
self.assertIn("Jane Doe", result)
|
354 |
+
self.assertIn("Senior Python Developer", result)
|
355 |
|
356 |
+
@patch('functions.gradio.write_resume')
|
357 |
+
@patch('functions.gradio.summarize_job_call')
|
358 |
@patch('functions.gradio.extract_text')
|
359 |
@patch('functions.gradio.get_github_repositories')
|
360 |
+
def test_process_inputs_none_github_username(
|
361 |
+
self,
|
362 |
+
mock_github,
|
363 |
+
mock_extract,
|
364 |
+
mock_job_call,
|
365 |
+
mock_write_resume
|
366 |
+
):
|
367 |
"""Test process_inputs with None github_username (should handle gracefully)."""
|
368 |
|
369 |
mock_extract.return_value = None
|
370 |
mock_github.return_value = None
|
371 |
+
mock_job_call.return_value = None
|
372 |
|
373 |
# This should raise a TypeError due to the bug in gradio.py
|
374 |
# where it tries to slice job_post_text[:100] when job_post_text is None
|
|
|
376 |
gradio.process_inputs(
|
377 |
linkedin_pdf_path=None,
|
378 |
github_username=None,
|
379 |
+
job_post_text=None
|
|
|
380 |
)
|
381 |
|
382 |
|
tests/test_resumate.py
CHANGED
@@ -19,8 +19,6 @@ class TestResumeGeneration(unittest.TestCase):
|
|
19 |
with open('tests/test_data/sample_job.txt', 'r', encoding='utf-8') as f:
|
20 |
self.job_post_text = f.read().strip()
|
21 |
|
22 |
-
self.user_instructions = ""
|
23 |
-
|
24 |
with open('tests/test_data/github_repos.json', 'r', encoding='utf-8') as f:
|
25 |
self.github_repositories = json.load(f)
|
26 |
|
@@ -38,7 +36,6 @@ class TestResumeGeneration(unittest.TestCase):
|
|
38 |
linkedin_pdf_path=self.linkedin_pdf_path,
|
39 |
github_username=self.github_username,
|
40 |
job_post_text=self.job_post_text,
|
41 |
-
user_instructions=self.user_instructions
|
42 |
)
|
43 |
|
44 |
print(result)
|
|
|
19 |
with open('tests/test_data/sample_job.txt', 'r', encoding='utf-8') as f:
|
20 |
self.job_post_text = f.read().strip()
|
21 |
|
|
|
|
|
22 |
with open('tests/test_data/github_repos.json', 'r', encoding='utf-8') as f:
|
23 |
self.github_repositories = json.load(f)
|
24 |
|
|
|
36 |
linkedin_pdf_path=self.linkedin_pdf_path,
|
37 |
github_username=self.github_username,
|
38 |
job_post_text=self.job_post_text,
|
|
|
39 |
)
|
40 |
|
41 |
print(result)
|