![]() ![]() Bouncer’s data model contains all of these, including several one-to-many and many-to-many relationships.Īfter I tried to populate my database using fixtures, I came across the following issues: “Complex” in this case refers to models containing datetimes, UUIDs, and especially foreign keys. Basic use cases, like a single unit tests with a simple data model can and should be dealt with using fixtures.įixtures become troublesome as soon as you start dealing with increasingly complex data models. The Django documentation even recommends them. I was convinced fixtures would be the solution to my problem. Fixtures are basically synonymous with JSON although they can also be XML, YAML, etc. □Ī fixture (in the Python/Django world) is a module for loading and referencing test data. Selfishly, I’d prefer to write Python scripts over Docker commands any day.What if Bouncer wasn’t Docker-ized? If we ever decided to move away from Docker we would be forced to revisit this problem.Bouncer is a newer service undergoing refactors, so the data model is constantly in flux. Any time the data model changes a new Docker image would need to be built, pushed, and pulled down by all the other Bouncer devs.What if a new use case required additional data for testing? Bouncer is then faced with the same inconvenience of manually creating data with no standardized way to do so. ![]() For these reasons, the approach was not ideal: Developers could then simply pull down the pre-loaded database image and be ready to go. Since Bouncer runs on Docker locally, another possible solution was to create a Docker image with the necessary data already loaded into the database. Perhaps it was my OCD, but this approach left me with a lot of insecurity about the accuracy and usefulness of my data, so I searched for another solution. ![]() A lot of the data in Bouncer’s staging environment survived a ton of migrations and manual manipulation, so my gut feeling was that tracking down these tiny issues would not be worth the time and effort.Īdditionally, most of the data in the staging environment looked like nonsensical garbage, as it was quickly and manually created to test one specific feature of Bouncer (it is staging, after all). The SQL dump loaded successfully but also produced a bunch of errors (e.g., relation already exists, random sequence issues, etc). My initial approach was to load a SQL dump from Bouncer’s staging environment into my local database container. Note: If you just want to skip the journey and just see the code, head to the ‘Implementation’ section below, or check out some example code on GitHub. Additionally, I wanted the output to be replicable and idempotent, so new engineers could run the same script and share the same starting point. We needed a bunch of sandbox data to work with, but generating useful, human-readable data was difficult and time consuming without a solid understanding of Bouncer’s complicated data models. However, Bouncer was difficult to develop and test locally because new containers would connect to an empty database and present a sparse user interface. Spinning up a local instance of Bouncer was simple thanks to the wonders of Docker. If a refresher is needed, the Django Tutorial (which I admittedly referenced while writing this post) should cover it. This post assumes some working knowledge of the typical Django app structure. After researching multiple approaches I was able to solve this problem by combining a number of tools/libraries into one clean implementation. When I started working on Bouncer, my team and I ran into a recurring issue with generating sandbox data that consumed a lot of our time. Bouncer is a CMS built on top of the Django framework and primarily talks to another internal Scala service. Since I started a few months ago, I’ve been working on a newer internal service called Bouncer. ![]() These services vary in language, visibility, and scale. # Items here will be available to further declarations, but won't beĭescription_contents = factory.Faker('paragraph')ĭescription = factory.LazyAttribute(lambda a: a.description_contents if a.Here at GIPHY we have a lot of services. This function also uses factory_boy's randomness management features.Īnother option would be to use parameters ( class Params): class MyFactory(): I've used 圜hoice to have that random computation performed for each object. Note that, in the code you shared, the title = "My title" if random() < 0.5 else None is computed exactly once, when Python parses the file. Title = 圜hoice()ĭescription = factory.Maybe('title', factory.Faker('paragraph')) The simplest way to achieve what you're looking for is to use factory.Maybe: class MyFactory(): Factory.Faker is a special object: when a factory instantiates an object, it will ask the factory.Faker proxy to get a random value from faker. ![]()
0 Comments
Leave a Reply. |
AuthorWrite something about yourself. No need to be fancy, just an overview. ArchivesCategories |