Skip to content

Commit 9f1d6d9

Browse files
committed
Add unit tests for Forced Alignment Client
* Introduced a new test module `test_forced_alignment_client.py` to validate the functionality of the `ForcedAlignmentClient`. * Implemented various test cases to ensure correct behavior for job submission and result retrieval. * Added tests for handling missing parameters and validating error messages. Signed-off-by: Ahmed Mansour <ahmed@loom.li>
1 parent 13c6102 commit 9f1d6d9

File tree

2 files changed

+258
-0
lines changed

2 files changed

+258
-0
lines changed

test.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1 +1,2 @@
11
import src.rev_ai.apiclient as client
2+
from src.rev_ai.forced_alignment_client import ForcedAlignmentClient
Lines changed: 257 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,257 @@
1+
# -*- coding: utf-8 -*-
2+
"""Unit tests for Forced Alignment Client"""
3+
4+
import json
5+
import pytest
6+
from src.rev_ai.forced_alignment_client import ForcedAlignmentClient
7+
from src.rev_ai import __version__
8+
from src.rev_ai.models.forced_alignment import ForcedAlignmentJob, ForcedAlignmentResult, Monologue, ElementAlignment
9+
from src.rev_ai.models import JobStatus, CustomerUrlData
10+
11+
try:
12+
from urllib.parse import urljoin
13+
except ImportError:
14+
from urlparse import urljoin
15+
16+
TOKEN = 'token'
17+
JOB_ID = '1'
18+
METADATA = 'test'
19+
MEDIA_URL = 'https://www.rev.ai/FTC_Sample_1.mp3'
20+
TRANSCRIPT_URL = 'https://www.rev.ai/FTC_Sample_1.txt'
21+
TRANSCRIPT_TEXT = """Hi, my name is Jack Groetzinger and I'm going to be talking about how to recruit a cofounder and a team for your startup. I'm going to first give a quick overview of what we're going to talk about. We're going to start out by talking about the sorts of folks you might be looking for for your startup. Then we'll dive right into tactics and approaches you can use to get inbound interest in your company. We'll talk a little bit about how to get people excited for your startup, and then we'll talk about the screening process, how to figure out if someone is a good match and someone you should make an offer to. We'll then cover how you make an offer and we'll wrap up by covering a few specific issues, one is technical hiring, which can be a little different from more general recruiting and finally we'll talk about specifically what you should do when you're looking for a cofounder. Many of the things we're going to be talking about are applicable to both finding a cofounder and finding employees, but there are a few specific issues that are relevant to when you're looking for a co-founder to be part of your startup, so we'll talk about that I want to give a quick background in myself, I am the cofounder of SeatGeek. We are a search engine for sports and concert tickets based in New York City, this is my third startup and for all three we built a team so I have some experience with this. At SeetGeek we have 17 folks and we have an incredible team. And I just want to talk about some things that we've done that I think have helped us get there as sort of the overall thesis for this, one thing that's worth keeping in mind is that recruiting is a lot of work. Some people think that you can raise money and spend a few weeks building your team and then move on to more interesting things, that's totally not the case, recruiting is something that you're always doing, I as a co-founder probably spend regularly 30% of my time trying to find new people to add to our team. But if you, you it's a lot of work because it's such an important thing to assess the success of a startup, and if you invest that time, then the dividends pay off."""
22+
CREATED_ON = '2025-01-11T22:42:23.45Z'
23+
LANGUAGE = 'en'
24+
25+
26+
class TestForcedAlignmentClient:
27+
def test_constructor_with_success(self):
28+
client = ForcedAlignmentClient(TOKEN)
29+
30+
headers = client.default_headers
31+
32+
assert headers.get('User-Agent') == 'RevAi-PythonSDK/{}'.format(__version__)
33+
assert headers.get('Authorization') == 'Bearer {}'.format(TOKEN)
34+
assert client.base_url == 'https://api.rev.ai/alignment/v1/'
35+
36+
@pytest.mark.parametrize('token', [None, ''])
37+
def test_constructor_with_no_token(self, token):
38+
with pytest.raises(ValueError, match='access_token must be provided'):
39+
ForcedAlignmentClient(token)
40+
41+
def test_submit_job_url_with_source_config_success(self, mock_session, make_mock_response):
42+
client = ForcedAlignmentClient(TOKEN)
43+
url = urljoin(client.base_url, 'jobs')
44+
source_config = CustomerUrlData(MEDIA_URL)
45+
transcript_text = TRANSCRIPT_TEXT
46+
data = {
47+
'id': JOB_ID,
48+
'created_on': CREATED_ON,
49+
'status': 'in_progress',
50+
'metadata': METADATA,
51+
'type': 'alignment',
52+
'language': LANGUAGE
53+
}
54+
response = make_mock_response(url=url, json_data=data)
55+
mock_session.request.return_value = response
56+
57+
res = client.submit_job_url(
58+
source_config=source_config,
59+
transcript_text=transcript_text,
60+
metadata=METADATA,
61+
language=LANGUAGE)
62+
63+
assert res == ForcedAlignmentJob(
64+
id=JOB_ID,
65+
created_on=CREATED_ON,
66+
status=JobStatus.IN_PROGRESS,
67+
metadata=METADATA,
68+
type='alignment')
69+
70+
mock_session.request.assert_called_once_with(
71+
"POST",
72+
url,
73+
json={
74+
'source_config': source_config.to_dict(),
75+
'transcript_text': transcript_text,
76+
'metadata': METADATA,
77+
'language': LANGUAGE
78+
},
79+
headers=client.default_headers)
80+
81+
def test_submit_job_url_with_transcript_config_success(self, mock_session, make_mock_response):
82+
client = ForcedAlignmentClient(TOKEN)
83+
url = urljoin(client.base_url, 'jobs')
84+
source_config = CustomerUrlData(MEDIA_URL)
85+
source_transcript_config = CustomerUrlData(TRANSCRIPT_URL)
86+
data = {
87+
'id': JOB_ID,
88+
'created_on': CREATED_ON,
89+
'status': 'in_progress',
90+
'metadata': METADATA,
91+
'type': 'alignment'
92+
}
93+
response = make_mock_response(url=url, json_data=data)
94+
mock_session.request.return_value = response
95+
96+
res = client.submit_job_url(
97+
source_config=source_config,
98+
source_transcript_config=source_transcript_config,
99+
metadata=METADATA)
100+
101+
assert res == ForcedAlignmentJob(
102+
id=JOB_ID,
103+
created_on=CREATED_ON,
104+
status=JobStatus.IN_PROGRESS,
105+
metadata=METADATA,
106+
type='alignment')
107+
108+
mock_session.request.assert_called_once_with(
109+
"POST",
110+
url,
111+
json={
112+
'source_config': source_config.to_dict(),
113+
'source_transcript_config': source_transcript_config.to_dict(),
114+
'metadata': METADATA
115+
},
116+
headers=client.default_headers)
117+
118+
def test_submit_job_url_missing_source_config(self):
119+
client = ForcedAlignmentClient(TOKEN)
120+
with pytest.raises(ValueError, match='source_config must be provided'):
121+
client.submit_job_url(transcript_text=TRANSCRIPT_TEXT)
122+
123+
def test_submit_job_url_missing_transcript(self):
124+
client = ForcedAlignmentClient(TOKEN)
125+
source_config = CustomerUrlData(MEDIA_URL)
126+
with pytest.raises(ValueError, match='Either source_transcript_config or transcript_text must be provided'):
127+
client.submit_job_url(source_config=source_config)
128+
129+
def test_submit_job_url_both_transcript_options(self):
130+
client = ForcedAlignmentClient(TOKEN)
131+
source_config = CustomerUrlData(MEDIA_URL)
132+
source_transcript_config = CustomerUrlData(TRANSCRIPT_URL)
133+
with pytest.raises(ValueError, match='Only one of source_transcript_config or transcript_text may be provided'):
134+
client.submit_job_url(
135+
source_config=source_config,
136+
source_transcript_config=source_transcript_config,
137+
transcript_text=TRANSCRIPT_TEXT)
138+
139+
def test_get_result_json_with_success(self, mock_session, make_mock_response):
140+
client = ForcedAlignmentClient(TOKEN)
141+
url = urljoin(client.base_url, 'jobs/{}/transcript'.format(JOB_ID))
142+
data = {
143+
'monologues': [
144+
{
145+
'speaker': 0,
146+
'elements': [
147+
{
148+
'type': 'text',
149+
'value': 'Hi',
150+
'ts': 0.25,
151+
'end_ts': 0.5
152+
},
153+
{
154+
'type': 'text',
155+
'value': 'my',
156+
'ts': 0.6,
157+
'end_ts': 0.75
158+
},
159+
{
160+
'type': 'text',
161+
'value': 'name',
162+
'ts': 0.8,
163+
'end_ts': 1.1
164+
},
165+
{
166+
'type': 'text',
167+
'value': 'is',
168+
'ts': 1.2,
169+
'end_ts': 1.3
170+
},
171+
{
172+
'type': 'text',
173+
'value': 'Jack',
174+
'ts': 1.4,
175+
'end_ts': 1.7
176+
}
177+
]
178+
}
179+
]
180+
}
181+
response = make_mock_response(url=url, json_data=data)
182+
mock_session.request.return_value = response
183+
184+
res = client.get_result_json(JOB_ID)
185+
186+
assert res == data
187+
mock_session.request.assert_called_once_with(
188+
"GET",
189+
url,
190+
headers=client.default_headers)
191+
192+
def test_get_result_object_with_success(self, mock_session, make_mock_response):
193+
client = ForcedAlignmentClient(TOKEN)
194+
url = urljoin(client.base_url, 'jobs/{}/transcript'.format(JOB_ID))
195+
data = {
196+
'monologues': [
197+
{
198+
'speaker': 0,
199+
'elements': [
200+
{
201+
'type': 'text',
202+
'value': 'Hi',
203+
'ts': 0.25,
204+
'end_ts': 0.5
205+
},
206+
{
207+
'type': 'text',
208+
'value': 'my',
209+
'ts': 0.6,
210+
'end_ts': 0.75
211+
},
212+
{
213+
'type': 'text',
214+
'value': 'name',
215+
'ts': 0.8,
216+
'end_ts': 1.1
217+
},
218+
{
219+
'type': 'text',
220+
'value': 'is',
221+
'ts': 1.2,
222+
'end_ts': 1.3
223+
},
224+
{
225+
'type': 'text',
226+
'value': 'Jack',
227+
'ts': 1.4,
228+
'end_ts': 1.7
229+
}
230+
]
231+
}
232+
]
233+
}
234+
response = make_mock_response(url=url, json_data=data)
235+
mock_session.request.return_value = response
236+
237+
res = client.get_result_object(JOB_ID)
238+
239+
assert res == ForcedAlignmentResult(
240+
monologues=[
241+
Monologue(
242+
speaker=0,
243+
elements=[
244+
ElementAlignment(value='Hi', ts=0.25, end_ts=0.5, type='text'),
245+
ElementAlignment(value='my', ts=0.6, end_ts=0.75, type='text'),
246+
ElementAlignment(value='name', ts=0.8, end_ts=1.1, type='text'),
247+
ElementAlignment(value='is', ts=1.2, end_ts=1.3, type='text'),
248+
ElementAlignment(value='Jack', ts=1.4, end_ts=1.7, type='text')
249+
]
250+
)
251+
]
252+
)
253+
254+
mock_session.request.assert_called_once_with(
255+
"GET",
256+
url,
257+
headers=client.default_headers)

0 commit comments

Comments
 (0)