Skip to content

Commit

Permalink
Unit tests (#15)
Browse files Browse the repository at this point in the history
* Add unit tests using requests-mock

* Add test_mock_job_run unit test

* Add test_mock_run_get_status unit test

Co-authored-by: Simo Tumelius <[email protected]>
  • Loading branch information
stumelius and datamie-simo authored Dec 23, 2021
1 parent 35c4bc6 commit 3cae73a
Show file tree
Hide file tree
Showing 13 changed files with 276 additions and 20 deletions.
10 changes: 2 additions & 8 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -242,12 +242,6 @@ This command prints a dbt Cloud run status JSON response. For more information o

```bash
>> dbt-cloud run get --run-id 36053848
Job 43167 run 34929305: QUEUED ...
Job 43167 run 34929305: QUEUED ...
Job 43167 run 34929305: QUEUED ...
Job 43167 run 34929305: STARTING ...
Job 43167 run 34929305: RUNNING ...
Job 43167 run 34929305: SUCCESS ...
{
"status": {
"code": 200,
Expand Down Expand Up @@ -302,8 +296,8 @@ Job 43167 run 34929305: SUCCESS ...
"duration_humanized": "1 minute, 50 seconds",
"queued_duration_humanized": "1 minute, 37 seconds",
"run_duration_humanized": "12 seconds",
"created_at_humanized": "34 minutes, 20 seconds ago",
"finished_at_humanized": "32 minutes, 29 seconds ago",
"created_at_humanized": "2 weeks, 1 day ago",
"finished_at_humanized": "2 weeks, 1 day ago",
"job_id": 43167
}
}
Expand Down
1 change: 1 addition & 0 deletions dbt_cloud/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
from .job import DbtCloudJob, DbtCloudRun
5 changes: 4 additions & 1 deletion dbt_cloud/cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ def run(wait, **kwargs):
)
time.sleep(5)
click.echo(json.dumps(response.json(), indent=2))
response.raise_for_status()


@job.command()
Expand All @@ -59,6 +60,7 @@ def get(**kwargs):
job = DbtCloudJob(**args.dict())
response = job.get(order_by=args.order_by)
click.echo(json.dumps(response.json(), indent=2))
response.raise_for_status()


@job.command()
Expand All @@ -68,7 +70,7 @@ def create(**kwargs):
job = DbtCloudJob(job_id=None, **args.dict())
response = job.create(args)
click.echo(json.dumps(response.json(), indent=2))
response.raise_for_status() # TODO: Align all commands with this control flow
response.raise_for_status()


@job_run.command()
Expand All @@ -78,3 +80,4 @@ def get(**kwargs):
run = args.get_run()
response, _ = run.get_status()
click.echo(json.dumps(response.json(), indent=2))
response.raise_for_status()
6 changes: 2 additions & 4 deletions dbt_cloud/job.py
Original file line number Diff line number Diff line change
Expand Up @@ -134,13 +134,12 @@ def get_api_url(self) -> str:
return f"{super().get_api_url()}/jobs/{self.job_id}"
return f"{super().get_api_url()}/jobs"

def get(self, order_by: str) -> requests.Response:
def get(self, order_by: str = None) -> requests.Response:
response = requests.get(
url=f"{self.get_api_url()}/",
headers={"Authorization": f"Token {self.api_token}"},
params={"order_by": order_by},
)
response.raise_for_status()
return response

def create(self, args: DbtCloudJobCreateArgs) -> requests.Response:
Expand All @@ -152,16 +151,15 @@ def create(self, args: DbtCloudJobCreateArgs) -> requests.Response:
return response

def run(self, args: DbtCloudJobRunArgs) -> Tuple[requests.Response, DbtCloudRun]:
assert str(args.job_id) == str(self.job_id), f"{args.job_id} != {self.job_id}"
response = requests.post(
url=f"{self.get_api_url()}/run/",
headers={"Authorization": f"Token {self.api_token}"},
json=args.get_payload(),
)
response.raise_for_status()
run_id = response.json()["data"]["id"]
return response, DbtCloudRun(
run_id=run_id,
args=args,
account_id=self.account_id,
api_token=self.api_token,
)
1 change: 0 additions & 1 deletion dbt_cloud/run.py
Original file line number Diff line number Diff line change
Expand Up @@ -41,5 +41,4 @@ def get_status(self) -> Tuple[requests.Response, DbtCloudRunStatus]:
url=f"{self.get_api_url()}/",
headers={"Authorization": f"Token {self.api_token}"},
)
response.raise_for_status()
return response, DbtCloudRunStatus(response.json()["data"]["status"])
2 changes: 1 addition & 1 deletion setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@
packages=["dbt_cloud"],
install_requires=["requests", "click", "pydantic"],
extras_require={
"test": ["pytest", "pytest-cov", "pytest-datadir"],
"test": ["pytest", "pytest-cov", "pytest-datadir", "requests-mock"],
"lint": ["black"],
},
scripts=[],
Expand Down
49 changes: 49 additions & 0 deletions tests/conftest.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
import json
import pytest
from dbt_cloud import DbtCloudJob, DbtCloudRun


def load_response(shared_datadir, response_name):
response_file = shared_datadir / f"{response_name}.json"
response_json = response_file.read_text()
return json.loads(response_json)


@pytest.fixture
def job_get_response(shared_datadir):
return load_response(shared_datadir, "job_get_response")


@pytest.fixture
def job_create_response(shared_datadir):
return load_response(shared_datadir, "job_create_response")


@pytest.fixture
def job_run_response(shared_datadir):
return load_response(shared_datadir, "job_run_response")


@pytest.fixture
def run_get_response(shared_datadir):
return load_response(shared_datadir, "run_get_response")


@pytest.fixture
def project_id():
return 123457


@pytest.fixture
def environment_id():
return 49819


@pytest.fixture
def job():
return DbtCloudJob(api_token="foo", account_id=123456, job_id=43167)


@pytest.fixture
def run(job):
return DbtCloudRun(run_id=36053848, **job.dict())
56 changes: 56 additions & 0 deletions tests/data/job_create_response.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
{
"status": {
"code": 201,
"is_success": true,
"user_message": "Success!",
"developer_message": ""
},
"data": {
"execution": {
"timeout_seconds": 0
},
"generate_docs": false,
"run_generate_sources": false,
"id": 48180,
"account_id": 123456,
"project_id": 123457,
"environment_id": 49819,
"name": "Dummy job",
"dbt_version": null,
"created_at": "2021-12-22T11:23:26.968076+00:00",
"updated_at": "2021-12-22T11:23:26.968094+00:00",
"execute_steps": [
"dbt seed",
"dbt run"
],
"state": 1,
"deferring_job_definition_id": null,
"lifecycle_webhooks": false,
"lifecycle_webhooks_url": null,
"triggers": {
"github_webhook": false,
"git_provider_webhook": null,
"custom_branch_only": false,
"schedule": false
},
"settings": {
"threads": 1,
"target_name": "default"
},
"schedule": {
"cron": "0 * * * *",
"date": {
"type": "every_day"
},
"time": {
"type": "every_hour",
"interval": 1
}
},
"is_deferrable": false,
"generate_sources": false,
"cron_humanized": "Every hour",
"next_run": null,
"next_run_humanized": null
}
}
59 changes: 59 additions & 0 deletions tests/data/job_run_response.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
{
"status": {
"code": 200,
"is_success": true,
"user_message": "Success!",
"developer_message": ""
},
"data": {
"id": 34929305,
"trigger_id": 35644346,
"account_id": 123456,
"environment_id": 49819,
"project_id": 123457,
"job_definition_id": 43167,
"status": 10,
"dbt_version": "0.21.0",
"git_branch": "main",
"git_sha": "981c5cf1ba299e942c6c277c38c8dec9b0738dd0",
"status_message": null,
"owner_thread_id": null,
"executed_by_thread_id": "dbt-run-34929305-dcmbq",
"deferring_run_id": null,
"artifacts_saved": true,
"artifact_s3_path": "prod/runs/34929305/artifacts/target",
"has_docs_generated": false,
"has_sources_generated": false,
"notifications_sent": true,
"blocked_by": [],
"scribe_enabled": true,
"created_at": "2021-11-26 16:48:41.431645+00:00",
"updated_at": "2021-11-26 16:49:33.078918+00:00",
"dequeued_at": "2021-11-26 16:49:15.670558+00:00",
"started_at": "2021-11-26 16:49:20.535987+00:00",
"finished_at": "2021-11-26 16:49:32.996703+00:00",
"last_checked_at": null,
"last_heartbeat_at": null,
"should_start_at": null,
"trigger": null,
"job": null,
"environment": null,
"run_steps": [],
"status_humanized": "Success",
"in_progress": false,
"is_complete": true,
"is_success": true,
"is_error": false,
"is_cancelled": false,
"href": "REDACTED",
"duration": "00:00:51",
"queued_duration": "00:00:39",
"run_duration": "00:00:12",
"duration_humanized": "51 seconds",
"queued_duration_humanized": "39 seconds",
"run_duration_humanized": "12 seconds",
"created_at_humanized": "1 minute ago",
"finished_at_humanized": "9 seconds ago",
"job_id": 43167
}
}
59 changes: 59 additions & 0 deletions tests/data/run_get_response.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
{
"status": {
"code": 200,
"is_success": true,
"user_message": "Success!",
"developer_message": ""
},
"data": {
"id": 36053848,
"trigger_id": 36768889,
"account_id": 123456,
"environment_id": 49819,
"project_id": 123457,
"job_definition_id": 43167,
"status": 10,
"dbt_version": "0.21.0",
"git_branch": "main",
"git_sha": "981c5cf1ba299e942c6c277c38c8dec9b0738dd0",
"status_message": null,
"owner_thread_id": null,
"executed_by_thread_id": "dbt-run-36053848-84vsp",
"deferring_run_id": null,
"artifacts_saved": true,
"artifact_s3_path": "prod/runs/36053848/artifacts/target",
"has_docs_generated": false,
"has_sources_generated": false,
"notifications_sent": true,
"blocked_by": [],
"scribe_enabled": true,
"created_at": "2021-12-07 10:32:24.326116+00:00",
"updated_at": "2021-12-07 10:34:14.507280+00:00",
"dequeued_at": "2021-12-07 10:33:54.599925+00:00",
"started_at": "2021-12-07 10:34:01.982824+00:00",
"finished_at": "2021-12-07 10:34:14.435474+00:00",
"last_checked_at": null,
"last_heartbeat_at": null,
"should_start_at": null,
"trigger": null,
"job": null,
"environment": null,
"run_steps": [],
"status_humanized": "Success",
"in_progress": false,
"is_complete": true,
"is_success": true,
"is_error": false,
"is_cancelled": false,
"href": "REDACTED",
"duration": "00:01:50",
"queued_duration": "00:01:37",
"run_duration": "00:00:12",
"duration_humanized": "1 minute, 50 seconds",
"queued_duration_humanized": "1 minute, 37 seconds",
"run_duration_humanized": "12 seconds",
"created_at_humanized": "2 weeks, 1 day ago",
"finished_at_humanized": "2 weeks, 1 day ago",
"job_id": 43167
}
}
32 changes: 32 additions & 0 deletions tests/test_job.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
from dbt_cloud.job import DbtCloudJob, DbtCloudJobCreateArgs, DbtCloudJobRunArgs


def test_mock_job_get(requests_mock, job, job_get_response):
url = job.get_api_url() + "/"
requests_mock.get(url, json=job_get_response, status_code=200)
response = job.get()
assert response.json() == job_get_response


def test_mock_job_create(
requests_mock, job, job_create_response, project_id, environment_id
):
url = job.get_api_url() + "/"
requests_mock.post(url, json=job_create_response, status_code=201)
args = DbtCloudJobCreateArgs(
project_id=project_id,
environment_id=environment_id,
name="Dummy job",
execute_steps=["dbt seed", "dbt run"],
)
response = job.create(args)
assert response.json() == job_create_response


def test_mock_job_run(requests_mock, job, job_run_response):
url = job.get_api_url() + "/run/"
requests_mock.post(url, json=job_run_response, status_code=200)
args = DbtCloudJobRunArgs()
response, job_run = job.run(args)
assert response.json() == job_run_response
assert job_run.run_id == job_run_response["data"]["id"]
7 changes: 2 additions & 5 deletions tests/test_job_import.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,8 @@
from dbt_cloud.job import DbtCloudJobCreateArgs


def test_job_args_import_from_json(shared_datadir):
response_file = shared_datadir / "job_get_response.json"
response_json = response_file.read_text()
response_dict = json.loads(response_json)
job_dict = response_dict["data"]
def test_job_args_import_from_json(job_get_response):
job_dict = job_get_response["data"]
args = DbtCloudJobCreateArgs(**job_dict)
assert args.environment_id == 49819
assert args.account_id == 123456
Expand Down
9 changes: 9 additions & 0 deletions tests/test_run.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
from dbt_cloud.run import DbtCloudRun, DbtCloudRunStatus


def test_mock_run_get_status(requests_mock, run, run_get_response):
url = run.get_api_url() + "/"
requests_mock.get(url, json=run_get_response, status_code=200)
response, run_status = run.get_status()
assert response.json() == run_get_response
assert run_status == DbtCloudRunStatus.SUCCESS

0 comments on commit 3cae73a

Please sign in to comment.