12/08/2018, 12:00

Tìm hiểu factory boy

Lời giới thiệu -Với những người từng sử dụng ngôn ngữ ruby on rails để phát triển những ứng dụng web hẳn không còn xa lạ gì với gem factory Girl, được sử dụng chủ yếu để sinh dữ liệu một cách nhanh chóng và hiệu quả. Đối với python, cũng có một công cụ hỗ trợ việc sinh ra dữ liệu nhanh hiệu ...

  1. Lời giới thiệu
    -Với những người từng sử dụng ngôn ngữ ruby on rails để phát triển những ứng dụng web hẳn không còn xa lạ gì với gem factory Girl, được sử dụng chủ yếu để sinh dữ liệu một cách nhanh chóng và hiệu quả. Đối với python, cũng có một công cụ hỗ trợ việc sinh ra dữ liệu nhanh hiệu quả không kém. Đó chính là bạn trai với factory_girl của rubyon rails, factory boy.

    -Factory_boy là một công cụ được viết dựa trên factory Girl, mục đích cũng chính là sinh ra dữ liệu , thuận tiện cho việc test các ứng dụng đang được xây dựng.

    -Việc cài đặt thêm factory boy vào môi trường phát triển cũng như cài đặt các gói khác, ta sử dụng lệnh :
    $ pip install factory_boy

  2. Sự tương quan giữa trường dữ liệu trong database và trường sử dụng trong factory boy

    Trường trong database Trường trong factoryBoy
    Date FuzzyDate
    text FuzzyText
    Integer FuzzyInteger
    Float FuzzyFloatl
    DateTime FuzzyDateTime

    Ngoài ra factory boy còn đảm bảo tốt các mối quan hệ của các bảng trong database.
    Trong đó những mối quan hệ phổ biến nhất là quan hệ một - nhiều (one to many) qua foreign key và quan hệ nhiều nhiều (many to many)

    • Quan hệ một nhiều được thể hiện trong database qua khóa Foreign Key thì trong factory boy được thể hiện qua trường subfactory
    • Quan hệ nhiều nhiều thông qua bảng trung gian (many to many through) được thể hiện, bản chất cũng là quan hệ một nhiều trong những trường hợp riêng lẻ. Hiện tại thì dường như Factory Boy chưa có hỗ trợ việc sử dụng manytomanyfield trong django model
  3. Việc sinh dữ liệu trong factory boy
    Để thực hiện chức năng sinh dữ liệu trong database để thực hiện các mục đích kiểm thử, Factory Boy vẫn sử dụng thư viện chính là Faker Factory (tương tự factory Girl trong rubyonrail). Ngoài ra nó còn xây dựng một số thủ tục (có thể cách gọi vẫn chưa được chính xác), hay được hiểu là cách mà lập trình viên có thể sử dụng để sinh ra dữ liệu:

    • Lazy Attributes: Hầu hết các thuộc tính khi định nghĩa một factory đều có thể sử dụng cách này để gán các giá trị tĩnh cho những trường giá trị, việc này khá là phổ biến khi fake data cho mục đích thử nghiệm .
      ví dụ:
        class UserFactory(factory.Factory):
            class Meta:
                model = models.User
            first_name = 'Joe'
            last_name = 'Blow'
            email = factory.LazyAttribute(lambda a: '{0}.{1}@example.com'.format(a.first_name, a.last_name).lower())
    

Khi trong python console:
Sử dụng: UserFactory().email
Kết quả nhận đươc: "joe.blow@example.com" - Sequences : Sử dụng để xây dựng những thuộc tính có giá trị duy nhất (unique) và có cấu trúc được xác định. ví dụ:
~~~ python class UserFactory(factory.Factory): class Meta: model = models.User email = factory.Sequence(lambda n: 'person{0}@example.com'.format(n)) ~~~ Trong python console, khi liên tiếp lặp lại câu lệnh: UserFactory().email, ta sẽ nhận được liên tiếp các kết quả như:
person0@example.com
person1@example.com...

  • Inheritance: Cũng giống sự kế thừa trong lập trình ngôn ngữ hướng đối tượng, Factory boy cũng hỗ trợ việc kế thừa, để dễ dàng hơn trong việc sử dụng vào lập trình sinh ra những dữ liệu, tránh sự dư thừa hay lặp lại code
  1. Một ví dụ đơn giản trong việc sử dụng Factory Boy
    Trong file model tôi có một model như sau:
    from django.db.models import(
        Model,
        ForeignKey,
        CharField,
        TextField,
        FloatField,
        DateTimeField,
    )
    class BaseModel(Model):
        ins_date = DateTimeField(auto_now_add=True)
        upd_date = DateTimeField(auto_now=True)
        class Meta:
            abstract = True
    class Category(BaseMode):
    	name = CharField(max_length=200)
    class Service(BaseModel):
        name = CharField(max_length=200)
        price = FloatField()
        description = TextField()
        category = ForeignKey(Category)
    

Khi đó file factory của model này sẽ có thể được định nghĩa như sau:

~~~ python
from factory import(
	Factory,
	SubFactory
)
from factory.fuzzy import (
	FuzzyText,
    FuzzyFloat
    FuzzyDateTime
    )
class BaseModelFactory(Factory)
	class Meta:
    	model = BaseModel
        abstract = True
    upd_date = FuzzyDateTime(date(2015, 9, 1), tz='UCT')
    ins_date = FuzzyDateTime(date(2015, 9, 1), tz='UCT')
class CategoryFactory(BaseModelFactory):
	name = FuzzyText(length=200, chars=string.ascii_letters, prefix=')
    class Meta:
    	model = Category
class ServiceFactory(BaseModelFactory):
	name = FuzzyText(length=200, chars=string.ascii_letters, prefix=')
    price = FuzzyFloat(0.0)
    description = FuzzyText(length=200, chars=string.ascii_letters, prefix=')
    category = SubFactory(CategoryFactory)
    class Meta:
    	model = Service
~~~

Những bài giới thiệu sâu hơn về factory boy sẽ được giới thiệu ở những phần sau
link tham khảo:

  • factory boy
  • factory girl
0