-
-
Notifications
You must be signed in to change notification settings - Fork 4k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Generation of test data factories for stubs and testing from Swagger #896
Comments
I'm sorry but I don't know any of those tools or libraries, so I have no idea if this is do-able, or if this is even an interesting idea or not. |
I don't know too. If you could provide an example, it will speed us to understand how it works and to see if we want to include it. |
No problem, Ill put up a demo of how Id use them Its like using the test data builder pattern in Java for tests that require models or mother objects. We use factory-girl because we can iterate quite a bit on APIs for our applications and its a pain to have to change our test and stubs because the model changes. |
Factories and mock dataThis is the standard practice in unit tests var response = [
{name: "first author", post_count: 1234, address: "1234 Angular Lane"},
{name: "second author", post_count: 5, address: "1 Google Way"},
{name: "third author", post_count: 23, address: "24 Facebook Court"},
{name: "fourth author", post_count: 18, address: "114 Twitter Drive"}
]
$httpBackend.whenGET('/authors').respond(200, response); We can replace the use of fixtures in tests with Factories (this definition using Rosie.js). In this case we are also using faker to generate default fake data. Factory.define('author')
.attr('id', faker.random.uuid )
.attr('name', faker.name.findName )
.attr('post_count', function () { return faker.random.number({max : 1234}); })
.attr('address', faker.address.streetAddress); We can now generate a list of authors like so: var response = Factory.buildList('author', 4); if I wanted to test for a specific attr I can do either of the following: var response = Factory.build('author', {name : 'Jacob Marley'}); the alternative is to reference the value passed in during assertion: response.name The same factory defined with factory-girl is: Factory.define('author', {
id : faker.random.uuid, // hopefully soon to be included, pull request by yours truly.
name : faker.name.findName,
post_count : function () {return faker.random.number({ max : 1234 })},
address : faker.address.streetAddress
})
var response = Factory.build('author'); The main advantage that factory-girl has over rosie (for front end development) is the ability to handle relations: Factory.define('book', {
author : Factory.assoc('author', 'id'), // this is our association with the author model
title : faker.company.catchPhrase,
blurb : faker.lorem.paragraph
}) If we want to include the model in the book object (this relation is stupid but just for illustration) we can do the following: Factory.define('book', {
author : Factory.assoc('author'), // in this case the model is included
title : faker.company.catchPhrase,
blurb : faker.lorem.paragraph
}) As you can see there is no coupling to the actual model, if its not needed specifically for the test. We only couple on the attribute name if necessary. It can also be used in stubs for the front end to generate data for UI tests. You can use them in Form Objects (a smaller more specialised page object) to generate the data for entry into a form and allow the developer to pass in the overrides that they need for testing. By wrapping the factory definitions in a UMD module we can now use them for unit tests (which in the case of angular run in the browser), or in UI test (which, when using Protractor, are run on the server in node.js). It might seem like a little bit more work (and in some cases it is), but it reduces the coupling in your application, and allows you to reduce the need for heavy mocking, and stubbing, which in turn leads to brittle tests. (function (root, factory) {
if (typeof define === "function" && define.amd) {
define(["faker", "Factory"], factory);
} else if (typeof exports === "object") {
module.exports = factory(require("faker"), require("Factory"));
} else {
factory(root.faker, root.Factory);
}
}(this, function (faker, Factory) {
// NOTE: this is where I defined my module implementation
Factory.define('author', {
id : faker.random.uuid, // hopefully soon to be included, pull request by yours truly.
name : faker.name.findName,
post_count : function () {return faker.random.number({ max : 1234 })},
address : faker.address.streetAddress
})
Factory.define('book', {
author : Factory.assoc('author'), // in this case the model is included
title : faker.company.catchPhrase,
blurb : faker.lorem.paragraph
})
})); Generation of factories from SwaggerIn the same way that client libraries are generated we can generate factories. We parse the DTO definition and pass the values to templates (moustach, underscrore, etc.). Enabling the generation of factories and client libraries significantly speeds up frontend development and allows for rapid iteration on REST APIs. It can also allows for validation of the retrieved models which, if done by hand, can be error prone and a significant drain on resources. |
This looks complex to me, I would like to focus on #897 and then we can see if can do your other requests |
Using the parser from #895 to generate test data factories using factory-girl and Faker.js to allow for more concise unit testing of functions requiring models. If the models are wrapped in a UMD, they can be reused for unit tests, stubs and UI/Visual regression tests.
The text was updated successfully, but these errors were encountered: