From 56b2a4780bfeee060e199ef8a154156add2db1c1 Mon Sep 17 00:00:00 2001 From: dunossauro Date: Sat, 7 Sep 2024 03:29:17 -0300 Subject: [PATCH] =?UTF-8?q?Adicionando=20exerc=C3=ADcios=20resolvidos=20na?= =?UTF-8?q?=20aula=2005?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- aulas/exercicios_resolvidos/aula_05.md | 101 ++++++++++++++++++++++++- codigo_das_aulas/05/fast_zero/app.py | 14 ++++ codigo_das_aulas/05/tests/test_app.py | 66 ++++++++++++++++ 3 files changed, 177 insertions(+), 4 deletions(-) diff --git a/aulas/exercicios_resolvidos/aula_05.md b/aulas/exercicios_resolvidos/aula_05.md index 9ca3946f..f3457037 100644 --- a/aulas/exercicios_resolvidos/aula_05.md +++ b/aulas/exercicios_resolvidos/aula_05.md @@ -5,14 +5,42 @@ Escrever um teste para o endpoint de POST (create_user) que contemple o cenário ### Solução -... +Para testar esse cenário, precisamos de um username que já esteja registrado na base de dados. Para isso, podemos usar a fixture de `user` que criamos. Ela é uma garantia que o valor já está inserido no banco de dados: + +```py title="/tests/test_app.py" hl_lines="1 5" +def test_create_user_should_return_400_username_exists__exercicio(client, user): + response = client.post( + '/users/', + json={ + 'username': user.username, + 'email': 'alice@example.com', + 'password': 'secret', + }, + ) + assert response.status_code == HTTPStatus.BAD_REQUEST + assert response.json() == {'detail': 'Username already exists'} +``` ## Exercício 02 Escrever um teste para o endpoint de POST (create_user) que contemple o cenário onde o e-mail já foi registrado. Validando o erro `#!python 400`. ### Solução -... +Para testar esse cenário, precisamos de um e-mail que já esteja registrado na base de dados. Para isso, podemos usar a fixture de `user` que criamos. Ela é uma garantia que o valor já está inserido no banco de dados: + +```py title="/tests/test_app.py" hl_lines="1 5" +def test_create_user_should_return_400_email_exists__exercicio(client, user): + response = client.post( + '/users/', + json={ + 'username': 'alice', + 'email': user.email, + 'password': 'secret', + }, + ) + assert response.status_code == HTTPStatus.BAD_REQUEST + assert response.json() == {'detail': 'Email already exists'} +``` ## Exercício 03 @@ -20,7 +48,32 @@ Atualizar os testes criados nos exercícios 1 e 2 da [aula 03](../03.md/#exercic ### Solução -... +O objetivo desse exercício não necessariamente uma atualização dos testes, mas o caso de uma execução para validar se os testes, como foram feitos ainda funcionariam nessa nova estrutura. + +Os meus testes da aula 03: + +```python +def test_delete_user_should_return_not_found__exercicio(client): + response = client.delete('/users/666') + + assert response.status_code == HTTPStatus.NOT_FOUND + assert response.json() == {'detail': 'User not found'} + + +def test_update_user_should_return_not_found__exercicio(client): + response = client.put( + '/users/666', + json={ + 'username': 'bob', + 'email': 'bob@example.com', + 'password': 'mynewpassword', + }, + ) + assert response.status_code == HTTPStatus.NOT_FOUND + assert response.json() == {'detail': 'User not found'} +``` + +Ao executar eles continuam passando. ## Exercício 04 @@ -29,4 +82,44 @@ Implementar o banco de dados para o endpoint de listagem por id, criado no exerc ### Solução -... +Esse exercício basicamente consiste em duas partes. A primeira é alterar o endpoint para usar o banco de dados. Isso pode ser feito de maneira simples injetando a dependência da `session`: + +```python +@app.get('/users/{user_id}', response_model=UserPublic) +def read_user__exercicio( + user_id: int, session: Session = Depends(get_session) +): + db_user = session.scalar(select(User).where(User.id == user_id)) + + if not db_user: + raise HTTPException( + status_code=HTTPStatus.NOT_FOUND, detail='User not found' + ) + + return db_user +``` + +A segunda parte é entender o que precisa ser feito nos testes para que eles consigam cobrir os dois casos previstos. O de sucesso e o de falha. + +O teste de sucesso continua passando, pois ele de fato não depende de nenhuma interação com o banco de dados: +```python +def test_get_user_should_return_not_found__exercicio(client): + response = client.get('/users/666') + + assert response.status_code == HTTPStatus.NOT_FOUND + assert response.json() == {'detail': 'User not found'} +``` + +Já o teste de sucesso, depende que exista um usuário na base dados. Com isso podemos usar a fixture de `user` tanto na chamada, quanto na validação dos dados: + +```python +def test_get_user___exercicio(client, user): + response = client.get(f'/users/{user.id}') + + assert response.status_code == HTTPStatus.OK + assert response.json() == { + 'username': user.username, + 'email': user.email, + 'id': user.id, + } +``` diff --git a/codigo_das_aulas/05/fast_zero/app.py b/codigo_das_aulas/05/fast_zero/app.py index 2c4fcac6..be14c9fb 100644 --- a/codigo_das_aulas/05/fast_zero/app.py +++ b/codigo_das_aulas/05/fast_zero/app.py @@ -87,3 +87,17 @@ def delete_user(user_id: int, session: Session = Depends(get_session)): session.commit() return {'message': 'User deleted'} + + +@app.get('/users/{user_id}', response_model=UserPublic) +def read_user__exercicio( + user_id: int, session: Session = Depends(get_session) +): + db_user = session.scalar(select(User).where(User.id == user_id)) + + if not db_user: + raise HTTPException( + status_code=HTTPStatus.NOT_FOUND, detail='User not found' + ) + + return db_user diff --git a/codigo_das_aulas/05/tests/test_app.py b/codigo_das_aulas/05/tests/test_app.py index 422bc97d..30049808 100644 --- a/codigo_das_aulas/05/tests/test_app.py +++ b/codigo_das_aulas/05/tests/test_app.py @@ -27,6 +27,72 @@ def test_create_user(client): } +def test_create_user_should_return_400_username_exists__exercicio( + client, user +): + response = client.post( + '/users/', + json={ + 'username': user.username, + 'email': 'alice@example.com', + 'password': 'secret', + }, + ) + assert response.status_code == HTTPStatus.BAD_REQUEST + assert response.json() == {'detail': 'Username already exists'} + + +def test_create_user_should_return_400_email_exists__exercicio(client, user): + response = client.post( + '/users/', + json={ + 'username': 'alice', + 'email': user.email, + 'password': 'secret', + }, + ) + assert response.status_code == HTTPStatus.BAD_REQUEST + assert response.json() == {'detail': 'Email already exists'} + + +def test_delete_user_should_return_not_found__exercicio(client): + response = client.delete('/users/666') + + assert response.status_code == HTTPStatus.NOT_FOUND + assert response.json() == {'detail': 'User not found'} + + +def test_update_user_should_return_not_found__exercicio(client): + response = client.put( + '/users/666', + json={ + 'username': 'bob', + 'email': 'bob@example.com', + 'password': 'mynewpassword', + }, + ) + assert response.status_code == HTTPStatus.NOT_FOUND + assert response.json() == {'detail': 'User not found'} + + +def test_get_user_should_return_not_found__exercicio(client): + response = client.get('/users/666') + + assert response.status_code == HTTPStatus.NOT_FOUND + assert response.json() == {'detail': 'User not found'} + + +def test_get_user___exercicio(client, user): + response = client.get(f'/users/{user.id}') + + assert response.status_code == HTTPStatus.OK + assert response.json() == { + 'username': user.username, + 'email': user.email, + 'id': user.id, + } + + def test_read_users(client): response = client.get('/users') assert response.status_code == HTTPStatus.OK