Repository: saleor/saleor

Issue:
Write tests for populatedb command
Module used for generating example data is not covered with tests. 


Discussion:

Resolving patch:
diff --git a/saleor/core/management/commands/populatedb.py b/saleor/core/management/commands/populatedb.py
--- a/saleor/core/management/commands/populatedb.py
+++ b/saleor/core/management/commands/populatedb.py
@@ -2,10 +2,10 @@
 from django.core.management.base import BaseCommand
 from django.db import connection
 
-from ....userprofile.models import User
 from ...utils.random_data import (
     create_orders, create_users, create_shipping_methods,
-    create_items_by_schema)
+    create_products_by_schema, create_product_sales, create_vouchers)
+from ...utils import create_superuser
 
 
 class Command(BaseCommand):
@@ -51,8 +51,12 @@ def handle(self, *args, **options):
         create_images = not options['withoutimages']
         for msg in create_shipping_methods():
             self.stdout.write(msg)
-        create_items_by_schema(self.placeholders_dir, 10, create_images,
-                               stdout=self.stdout)
+        create_products_by_schema(self.placeholders_dir, 10, create_images,
+                                  stdout=self.stdout)
+        for msg in create_product_sales(5):
+            self.stdout.write(msg)
+        for msg in create_vouchers():
+            self.stdout.write(msg)
         for msg in create_users(20):
             self.stdout.write(msg)
         for msg in create_orders(20):
@@ -60,16 +64,7 @@ def handle(self, *args, **options):
 
         if options['createsuperuser']:
             credentials = {'email': 'admin@example.com', 'password': 'admin'}
-            user, created = User.objects.get_or_create(
-                email=credentials['email'], defaults={
-                    'is_active': True, 'is_staff': True, 'is_superuser': True})
-            if created:
-                user.set_password(credentials['password'])
-                user.save()
-                self.stdout.write(
-                    'Superuser - %(email)s/%(password)s' % credentials)
-            else:
-                self.stdout.write(
-                    'Superuser already exists - %(email)s' % credentials)
+            msg = create_superuser(credentials)
+            self.stdout.write(msg)
         if not options['withoutsearch']:
             self.populate_search_index()
diff --git a/saleor/core/utils/__init__.py b/saleor/core/utils/__init__.py
--- a/saleor/core/utils/__init__.py
+++ b/saleor/core/utils/__init__.py
@@ -14,6 +14,8 @@
 from geolite2 import geolite2
 from prices import PriceRange
 
+from ...userprofile.models import User
+
 try:
     from urllib.parse import urljoin
 except ImportError:
@@ -105,3 +107,16 @@ def serialize_decimal(obj):
     if isinstance(obj, decimal.Decimal):
         return str(obj)
     return JSONEncoder.default(obj)
+
+
+def create_superuser(credentials):
+    user, created = User.objects.get_or_create(
+        email=credentials['email'], defaults={
+            'is_active': True, 'is_staff': True, 'is_superuser': True})
+    if created:
+        user.set_password(credentials['password'])
+        user.save()
+        msg = 'Superuser - %(email)s/%(password)s' % credentials
+    else:
+        msg = 'Superuser already exists - %(email)s' % credentials
+    return msg
diff --git a/saleor/core/utils/random_data.py b/saleor/core/utils/random_data.py
--- a/saleor/core/utils/random_data.py
+++ b/saleor/core/utils/random_data.py
@@ -13,6 +13,7 @@
 from faker.providers import BaseProvider
 from prices import Price
 
+from ...discount.models import Sale, Voucher
 from ...order.models import DeliveryGroup, Order, OrderedItem, Payment
 from ...product.models import (AttributeChoiceValue, Category, Product,
                                ProductAttribute, ProductClass, ProductImage,
@@ -125,8 +126,8 @@ def set_product_attributes(product, product_class):
 
 def set_variant_attributes(variant, product_class):
     attr_dict = {}
-    existing_variants = variant.product.variants.values_list(
-        'attributes', flat=True)
+    existing_variants = variant.product.variants.values_list('attributes',
+                                                             flat=True)
     existing_variant_attributes = defaultdict(list)
     for variant_attrs in existing_variants:
         for attr_id, value_id in variant_attrs.items():
@@ -166,9 +167,9 @@ def get_price_override(schema):
         return fake.price()
 
 
-def create_items_by_class(product_class, schema,
-                          placeholder_dir, how_many=10, create_images=True,
-                          stdout=None):
+def create_products_by_class(product_class, schema,
+                             placeholder_dir, how_many=10, create_images=True,
+                             stdout=None):
     category_name = schema.get('category') or DEFAULT_CATEGORY
     category = get_or_create_category(category_name)
 
@@ -193,10 +194,10 @@ def create_items_by_class(product_class, schema,
                 product, product_class.name, len(variant_combinations) or 1))
 
 
-def create_items_by_schema(placeholder_dir, how_many, create_images, stdout,
-                           schema=DEFAULT_SCHEMA):
+def create_products_by_schema(placeholder_dir, how_many, create_images,
+                              stdout=None, schema=DEFAULT_SCHEMA):
     for product_class, class_schema in create_product_classes_by_schema(schema):
-        create_items_by_class(
+        create_products_by_class(
             product_class, class_schema, placeholder_dir,
             how_many=how_many, create_images=create_images, stdout=stdout)
 
@@ -386,7 +387,7 @@ def create_order_lines(delivery_group, how_many=10):
 
 def create_fake_order():
     user = random.choice([None, User.objects.filter(
-        is_superuser=False).order_by('?')[0]])
+        is_superuser=False).order_by('?').first()])
     if user:
         user_data = {
             'user': user,
@@ -417,6 +418,16 @@ def create_fake_order():
     return order
 
 
+def create_fake_sale():
+    sale = Sale.objects.create(
+        name='Happy %s day!' % fake.word(),
+        type=Sale.PERCENTAGE,
+        value=random.choice([10, 20, 30, 40, 50]))
+    for product in Product.objects.all().order_by('?')[:4]:
+        sale.products.add(product)
+    return sale
+
+
 def create_users(how_many=10):
     for dummy in range(how_many):
         user = create_fake_user()
@@ -429,6 +440,12 @@ def create_orders(how_many=10):
         yield 'Order: %s' % (order,)
 
 
+def create_product_sales(how_many=5):
+    for dummy in range(how_many):
+        sale = create_fake_sale()
+        yield 'Sale: %s' % (sale,)
+
+
 def create_shipping_methods():
     shipping_method = ShippingMethod.objects.create(name='UPC')
     shipping_method.price_per_country.create(price=fake.price())
@@ -436,3 +453,28 @@ def create_shipping_methods():
     shipping_method = ShippingMethod.objects.create(name='DHL')
     shipping_method.price_per_country.create(price=fake.price())
     yield 'Shipping method #%d' % shipping_method.id
+
+
+def create_vouchers():
+    voucher, created = Voucher.objects.get_or_create(
+        code='FREESHIPPING', defaults={
+            'type': Voucher.SHIPPING_TYPE,
+            'name': 'Free shipping',
+            'discount_value_type': Voucher.DISCOUNT_VALUE_PERCENTAGE,
+            'discount_value': 100})
+    if created:
+        yield 'Voucher #%d' % voucher.id
+    else:
+        yield 'Shipping voucher already exists'
+
+    voucher, created = Voucher.objects.get_or_create(
+        code='DISCOUNT', defaults={
+            'type': Voucher.VALUE_TYPE,
+            'name': 'Big order discount',
+            'discount_value_type': Voucher.DISCOUNT_VALUE_FIXED,
+            'discount_value': 25,
+            'limit': 200})
+    if created:
+        yield 'Voucher #%d' % voucher.id
+    else:
+        yield 'Value voucher already exists'


Test patch:
diff --git a/tests/test_core.py b/tests/test_core.py
--- a/tests/test_core.py
+++ b/tests/test_core.py
@@ -2,7 +2,26 @@
 from mock import Mock
 
 from saleor.core.utils import (
-    Country, get_country_by_ip, get_currency_for_country)
+    Country, create_superuser, get_country_by_ip, get_currency_for_country,
+    random_data)
+from saleor.discount.models import Sale, Voucher
+from saleor.order.models import Order
+from saleor.product.models import Product
+from saleor.shipping.models import ShippingMethod
+from saleor.userprofile.models import Address, User
+
+
+class_schema = {'Vegetable': {
+                   'category': 'Food',
+                   'product_attributes': {
+                       'Sweetness': ['Sweet', 'Sour'],
+                       'Healthiness': ['Healthy', 'Not really']
+                   },
+                   'variant_attributes': {
+                       'GMO': ['Yes', 'No']
+                   },
+                   'images_dir': 'candy/',
+                   'is_shipping_required': True}}
 
 
 @pytest.mark.parametrize('ip_data, expected_country', [
@@ -26,3 +45,101 @@ def test_get_country_by_ip(ip_data, expected_country, monkeypatch):
 def test_get_currency_for_country(country, expected_currency, monkeypatch):
     currency = get_currency_for_country(country)
     assert currency == expected_currency
+
+
+def test_create_superuser(db, client):
+    credentials = {'email': 'admin@example.com', 'password': 'admin'}
+    # Test admin creation
+    assert User.objects.all().count() == 0
+    create_superuser(credentials)
+    assert User.objects.all().count() == 1
+    admin = User.objects.all().first()
+    assert admin.is_superuser
+    # Test duplicating
+    create_superuser(credentials)
+    assert User.objects.all().count() == 1
+    # Test logging in
+    response = client.post('/account/login/',
+                           {'login': credentials['email'],
+                            'password': credentials['password']},
+                           follow=True)
+    assert response.context['request'].user == admin
+
+
+def test_create_shipping_methods(db):
+    assert ShippingMethod.objects.all().count() == 0
+    for _ in random_data.create_shipping_methods():
+        pass
+    assert ShippingMethod.objects.all().count() == 2
+
+
+def test_create_fake_user(db):
+    assert User.objects.all().count() == 0
+    random_data.create_fake_user()
+    assert User.objects.all().count() == 1
+    user = User.objects.all().first()
+    assert not user.is_superuser
+
+
+def test_create_fake_users(db):
+    how_many = 5
+    for _ in random_data.create_users(how_many):
+        pass
+    assert User.objects.all().count() == 5
+
+
+def test_create_address(db):
+    assert Address.objects.all().count() == 0
+    random_data.create_address()
+    assert Address.objects.all().count() == 1
+
+
+def test_create_attribute(db):
+    data = {'name': 'best_attribute', 'display': 'Best attribute'}
+    attribute = random_data.create_attribute(**data)
+    assert attribute.name == data['name']
+    assert attribute.display == data['display']
+
+
+def test_create_product_classes_by_schema(db):
+    p_class = random_data.create_product_classes_by_schema(class_schema)[0][0]
+    assert p_class.name == 'Vegetable'
+    assert p_class.product_attributes.count() == 2
+    assert p_class.variant_attributes.count() == 1
+    assert p_class.is_shipping_required
+
+
+def test_create_products_by_class(db):
+    assert Product.objects.all().count() == 0
+    how_many = 5
+    p_class = random_data.create_product_classes_by_schema(class_schema)[0][0]
+    random_data.create_products_by_class(p_class, class_schema['Vegetable'],
+                                         '/', how_many=how_many,
+                                         create_images=False)
+    assert Product.objects.all().count() == how_many
+
+
+def test_create_fake_order(db):
+    for _ in random_data.create_shipping_methods():
+        pass
+    for _ in random_data.create_users(3):
+        pass
+        random_data.create_products_by_schema('/', 10, False)
+    how_many = 5
+    for _ in random_data.create_orders(how_many):
+        pass
+    Order.objects.all().count() == 5
+
+
+def test_create_product_sales(db):
+    how_many = 5
+    for _ in random_data.create_product_sales(how_many):
+        pass
+    assert Sale.objects.all().count() == 5
+
+
+def test_create_vouchers(db):
+    assert Voucher.objects.all().count() == 0
+    for _ in random_data.create_vouchers():
+        pass
+    assert Voucher.objects.all().count() == 2