Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

pytest, mock dynamo #7

Merged
merged 12 commits into from
Nov 29, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 6 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,12 +16,14 @@ Go to your jazz-charts-api folder:

Run queries in Graphi at https://localhost:8000/graphql

## Run Tests

`TABLE_NAME=jazz-charts-test python -m pytest`

*Composer*

* getComposer

* allComposers

* createComposer

* updateComposer
Expand All @@ -31,8 +33,6 @@ Run queries in Graphi at https://localhost:8000/graphql

* getSong

* allSongs

* createSong

* updateSong
Expand All @@ -43,7 +43,7 @@ Example Query:
{
getComposer(id: "c1") {
id
name
fullName
songs {
id
title
Expand All @@ -60,7 +60,7 @@ Example Response:
"data": {
"getComposer": {
"id": "c1",
"name": "Jerome Kern",
"fullName": "Jerome Kern",
"songs": [
{
"id": "1",
Expand Down
1 change: 0 additions & 1 deletion app.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@
from flask import Flask, request, jsonify
from features.Composers.composer import resolve_composer, update_composer, resolve_composer, create_composer
from features.Songs.song import create_song, resolve_song, update_song

queryTypes = load_schema_from_path("./root_types/queries.gql")
mutationTypes = load_schema_from_path("./root_types/mutations.gql")

Expand Down
9 changes: 6 additions & 3 deletions aws_resources/dynamo.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
import boto3
import os
dynamodb = boto3.resource('dynamodb')
table_name = os.environ['TABLE_NAME']
table = dynamodb.Table(table_name)

def table():
dynamodb = boto3.resource('dynamodb')
table_name = os.environ['TABLE_NAME']
table = dynamodb.Table(table_name)
return table

def build_update_expression(items):
keys = items.keys()
Expand Down
74 changes: 74 additions & 0 deletions aws_resources/mock_dynamo.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@

from moto import mock_dynamodb2
import boto3
import os

mock_create_song = {
"title": "It don't mean a thing",
"chordChart": "Gm | ...",
"composer": "c1"
}

mock_song = {
'id': '1',
"title": "It don't mean a thing",
"chordChart": "Gm | ...",
"composer": "c1"
}

another_mock_song = {
'id': '2',
"title": "It don't mean a thing",
"chordChart": "Gm | ...",
"composer": "c1"
}

mock_composer = {
'id': 'c1',
'songs': [
'1',
'2'
],
'fullName': 'Duke Ellington'
}

mock_create_composer = {
'songs': [
'1',
'2'
],
'fullName': 'Duke Ellington'
}


@mock_dynamodb2
def setup_mocks():
dynamodb = boto3.resource('dynamodb')

table = dynamodb.create_table(
TableName= os.environ['TABLE_NAME'],
KeySchema=[
{
'AttributeName': 'id',
'KeyType': 'HASH' # primary key
}
],
AttributeDefinitions=[
{
'AttributeName': 'id',
'AttributeType': 'S'
},
],
)

table.put_item(
Item=mock_composer
)

table.put_item(
Item=mock_song
)

table.put_item(
Item=another_mock_song
)
6 changes: 3 additions & 3 deletions features/Composers/composer.gql
Original file line number Diff line number Diff line change
@@ -1,18 +1,18 @@
type FBComposer {
id: String
songs: [FBSong]
name: String
fullName: String
}

input FBComposerCreateInput {
songs: [String]
name: String
fullName: String
}

input FBComposerUpdateInput {
id: String!
songs: [String]
name: String
fullName: String
}

type FakeBookComposerResponse implements FakeBookResponse {
Expand Down
8 changes: 4 additions & 4 deletions features/Composers/composer.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,15 +5,15 @@
def resolve_composer(obj, info, id=None):
if (obj and 'composer' in obj):
id = obj['composer']
composer = table.query(
composer = table().query(
KeyConditionExpression=Key('id').eq(id)
)['Items'][0]
return composer

def create_composer(obj, info, composer):
id = str(uuid.uuid4())
composer['id'] = id
table.put_item(Item=composer)
table().put_item(Item=composer)
return {
'composer': composer,
'message': 'success',
Expand All @@ -24,14 +24,14 @@ def create_composer(obj, info, composer):
def update_composer(obj, info, composer):
attributes_to_update = build_update_attributes_dictionary(composer)
update_expression = build_update_expression(composer)
table.update_item(
table().update_item(
Key={
'id': composer['id']
},
UpdateExpression=update_expression,
ExpressionAttributeValues=attributes_to_update,
)
updated_composer = table.query(
updated_composer = table().query(
KeyConditionExpression=Key('id').eq(composer['id'])
)['Items'][0]

Expand Down
24 changes: 24 additions & 0 deletions features/Composers/tests/test_composer.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@

from features.Composers.composer import resolve_composer, create_composer, update_composer
from aws_resources.mock_dynamo import setup_mocks, mock_composer, mock_create_composer
from moto import mock_dynamodb2

@mock_dynamodb2
def test_resolve_composer():
setup_mocks()
composer = resolve_composer({}, {}, "c1")
assert composer == mock_composer

@mock_dynamodb2
def test_create_composer():
setup_mocks()
response = create_composer({}, {}, mock_create_composer)
assert response['message'] == 'success' and response['composer']['fullName'] == 'Duke Ellington'

@mock_dynamodb2
def test_update_composer():
setup_mocks()
new_attr = {'fullName': 'Ornett Coleman'}
updated_composer = {**mock_composer, **new_attr}
response = update_composer({}, {}, updated_composer)
assert response['message'] == 'success' and response['composer']['fullName'] == 'Ornett Coleman'
8 changes: 4 additions & 4 deletions features/Songs/song.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
import uuid

def resolve_song(obj, info, id):
song = table.query(
song = table().query(
KeyConditionExpression=Key('id').eq(id)
)['Items'][0]
return song
Expand All @@ -16,7 +16,7 @@ def resolve_songs(obj, info):
def create_song(obj, info, song):
id = str(uuid.uuid4())
song['id'] = id
table.put_item(Item=song)
table().put_item(Item=song)
return {
'song': song,
'message': 'success',
Expand All @@ -27,14 +27,14 @@ def create_song(obj, info, song):
def update_song(obj, info, song):
attributes_to_update = build_update_attributes_dictionary(song)
update_expression = build_update_expression(song)
table.update_item(
table().update_item(
Key={
'id': song['id']
},
UpdateExpression=update_expression,
ExpressionAttributeValues=attributes_to_update,
)
updated_song = table.query(
updated_song = table().query(
KeyConditionExpression=Key('id').eq(song['id'])
)['Items'][0]

Expand Down
30 changes: 30 additions & 0 deletions features/Songs/tests/test_song.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@

from features.Songs.song import resolve_song, resolve_songs, create_song, update_song
from aws_resources.mock_dynamo import setup_mocks, mock_song, another_mock_song, mock_create_song
from moto import mock_dynamodb2

@mock_dynamodb2
def test_resolve_song():
setup_mocks()
song = resolve_song({}, {}, "1")
assert song == mock_song

@mock_dynamodb2
def test_resolve_song():
setup_mocks()
songs = list(resolve_songs({'songs': ["1", "2"]}, {}))
assert songs == [mock_song, another_mock_song]

@mock_dynamodb2
def test_create_song():
setup_mocks()
response = create_song({}, {}, mock_create_song)
assert response['message'] == 'success' and response['song']['title'] == 'It don\'t mean a thing'

@mock_dynamodb2
def test_update_song():
setup_mocks()
new_attr = {'title': 'new song title'}
updated_song = {**mock_song, **new_attr}
response = update_song({}, {}, updated_song)
assert response['message'] == 'success' and response['song']['title'] == 'new song title'
50 changes: 48 additions & 2 deletions requirements.txt
Original file line number Diff line number Diff line change
@@ -1,33 +1,79 @@
ariadne==0.7.0
astroid==2.3.3
boto3==1.10.26
botocore==1.13.26
attrs==19.3.0
aws-sam-translator==1.16.0
aws-xray-sdk==0.95
boto==2.49.0
boto3==1.10.28
botocore==1.13.28
certifi==2019.11.28
cffi==1.13.2
cfn-lint==0.25.5
chardet==3.0.4
Click==7.0
cookies==2.2.1
cryptography==2.8
Cython==0.29.14
docker==4.1.0
docutils==0.15.2
ecdsa==0.14.1
Flask==1.1.1
Flask-UUID==0.2
future==0.18.2
GraphQL-core-next==1.1.1
h11==0.8.1
httptools==0.0.13
idna==2.8
importlib-metadata==0.23
isort==4.3.21
itsdangerous==1.1.0
Jinja2==2.10.3
jmespath==0.9.4
jsondiff==1.1.2
jsonpatch==1.24
jsonpickle==1.2
jsonpointer==2.0
jsonschema==3.2.0
lazy-object-proxy==1.4.3
MarkupSafe==1.1.1
mccabe==0.6.1
mock==3.0.5
more-itertools==7.2.0
moto==1.3.14
packaging==19.2
pluggy==0.13.1
py==1.8.0
pyaml==19.4.1
pyasn1==0.4.8
pycparser==2.19
pycryptodome==3.9.4
pylint==2.4.4
pynamodb==4.2.0
pyparsing==2.4.5
pyramda==0.1
pyrsistent==0.15.6
pytest==5.3.1
python-dateutil==2.8.0
python-jose==2.0.2
python-multipart==0.0.5
pytz==2019.3
PyYAML==5.1.2
requests==2.22.0
responses==0.10.7
rsa==4.0
s3transfer==0.2.1
six==1.13.0
sshpubkeys==3.1.0
starlette==0.12.13
typed-ast==1.4.0
typing-extensions==3.7.4.1
urllib3==1.25.7
uvicorn==0.10.8
uvloop==0.14.0
wcwidth==0.1.7
websocket-client==0.56.0
websockets==8.1
Werkzeug==0.16.0
wrapt==1.11.2
xmltodict==0.12.0
zipp==0.6.0