mirror of
https://github.com/HackSoftware/Django-Styleguide.git
synced 2024-11-10 19:56:40 +03:00
Merge pull request #89 from HackSoftware/improve-testing-sections-a-bit
Improve testing sections a bit
This commit is contained in:
commit
e76d5a8b27
55
README.md
55
README.md
|
@ -60,6 +60,7 @@
|
|||
- [More ideas](#more-ideas)
|
||||
- [Testing](#testing-2)
|
||||
- [Naming conventions](#naming-conventions)
|
||||
- [Factories](#factories)
|
||||
- [Celery](#celery)
|
||||
- [The basics](#the-basics)
|
||||
- [Error handling](#error-handling)
|
||||
|
@ -799,12 +800,14 @@ When creating the required state for a given test, one can use a combination of:
|
|||
```python
|
||||
from django.contrib.auth.models import User
|
||||
from django.core.exceptions import ValidationError
|
||||
from django.db import transaction
|
||||
|
||||
from project.payments.selectors import items_get_for_user
|
||||
from project.payments.models import Item, Payment
|
||||
from project.payments.tasks import payment_charge
|
||||
|
||||
|
||||
@transaction.atomic
|
||||
def item_buy(
|
||||
*,
|
||||
item: Item,
|
||||
|
@ -813,13 +816,19 @@ def item_buy(
|
|||
if item in items_get_for_user(user=user):
|
||||
raise ValidationError(f'Item {item} already in {user} items.')
|
||||
|
||||
payment = Payment.objects.create(
|
||||
payment = Payment(
|
||||
item=item,
|
||||
user=user,
|
||||
successful=False
|
||||
)
|
||||
payment.full_clean()
|
||||
payment.save()
|
||||
|
||||
payment_charge.delay(payment_id=payment.id)
|
||||
# Run the task once the transaction has commited,
|
||||
# guaranteeing the object has been created.
|
||||
transaction.on_commit(
|
||||
lambda: payment_charge.delay(payment_id=payment.id)
|
||||
)
|
||||
|
||||
return payment
|
||||
```
|
||||
|
@ -844,33 +853,40 @@ from django_styleguide.payments.models import Payment, Item
|
|||
|
||||
|
||||
class ItemBuyTests(TestCase):
|
||||
def setUp(self):
|
||||
self.user = User.objects.create_user(username='Test User')
|
||||
self.item = Item.objects.create(
|
||||
name='Test Item',
|
||||
description='Test Item description',
|
||||
price=10.15
|
||||
)
|
||||
|
||||
@patch('project.payments.services.items_get_for_user')
|
||||
def test_buying_item_that_is_already_bought_fails(self, items_get_for_user_mock):
|
||||
"""
|
||||
Since we already have tests for `items_get_for_user`,
|
||||
we can safely mock it here and give it a proper return value.
|
||||
"""
|
||||
items_get_for_user_mock.return_value = [self.item]
|
||||
user = User(username='Test User')
|
||||
item = Item(
|
||||
name='Test Item',
|
||||
description='Test Item description',
|
||||
price=10.15
|
||||
)
|
||||
|
||||
items_get_for_user_mock.return_value = [item]
|
||||
|
||||
with self.assertRaises(ValidationError):
|
||||
item_buy(user=self.user, item=self.item)
|
||||
item_buy(user=user, item=item)
|
||||
|
||||
@patch('project.payments.services.payment_charge.delay')
|
||||
def test_buying_item_creates_a_payment_and_calls_charge_task(
|
||||
self,
|
||||
payment_charge_mock
|
||||
):
|
||||
# How we prepare our tests is a topic for a different discussion
|
||||
user = given_a_user(username="Test user")
|
||||
item = given_a_item(
|
||||
name='Test Item',
|
||||
description='Test Item description',
|
||||
price=10.15
|
||||
)
|
||||
|
||||
self.assertEqual(0, Payment.objects.count())
|
||||
|
||||
payment = item_buy(user=self.user, item=self.item)
|
||||
payment = item_buy(user=user, item=item)
|
||||
|
||||
self.assertEqual(1, Payment.objects.count())
|
||||
self.assertEqual(payment, Payment.objects.first())
|
||||
|
@ -2338,6 +2354,7 @@ project_name
|
|||
│ ├── __init__.py
|
||||
│ └── tests
|
||||
│ ├── __init__.py
|
||||
│ ├── factories.py
|
||||
│ ├── models
|
||||
│ │ └── __init__.py
|
||||
│ │ └── test_some_model_name.py
|
||||
|
@ -2388,6 +2405,18 @@ If we are to split the `utils.py` module into submodules, the same will happen f
|
|||
|
||||
We try to match the structure of our modules with the structure of their respective tests.
|
||||
|
||||
### Factories
|
||||
|
||||
Factories are a great tool for generating data for your tests.
|
||||
|
||||
When used correctly, you can improve the overall quality of your tests.
|
||||
|
||||
If you are new to this concept, you can refer to the following materials:
|
||||
|
||||
- [Improve your Django tests with fakes and factories](https://www.hacksoft.io/blog/improve-your-tests-django-fakes-and-factories)
|
||||
- [https://www.hacksoft.io/blog/improve-your-tests-django-fakes-and-factories-advanced-usage](https://www.hacksoft.io/blog/improve-your-tests-django-fakes-and-factories-advanced-usage)
|
||||
- [DjangoCon 2022 | factory_boy: testing like a pro](https://www.youtube.com/watch?v=-C-XNHAJF-c)
|
||||
|
||||
## Celery
|
||||
|
||||
We use [Celery](http://www.celeryproject.org/) for the following general cases:
|
||||
|
|
Loading…
Reference in New Issue
Block a user