Skip to content
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

New Project to improving tests #1283

Open
juniorjrjl opened this issue Jul 1, 2024 · 9 comments
Open

New Project to improving tests #1283

juniorjrjl opened this issue Jul 1, 2024 · 9 comments

Comments

@juniorjrjl
Copy link

juniorjrjl commented Jul 1, 2024

Is your feature request related to a problem? Please describe.
No exactly problem,I have suggest to generate random objects to use in tests. ex.:
I have a User class and I have class who will generate instances with random data in all properties, but insetad of create a class to generate instances, we could use annotation processor to generate this classes.

Describe the solution you'd like
Look at my repository

https://github.com/juniorjrjl/jfaker/
docs.:
https://github.com/juniorjrjl/jfaker/wiki

I create a projetc who using annotation processor to create Bot class, this bot class will generate instances with random data and a data provider is a datafaker, I suggest a new project who will use a datafaker.

feel free to use my code and improve it to create a new project

Introduction

What is a JFaker

JFaker is a lib who use annotation processor to create bot class who create instances of your project class with random data for you worry only to create your test, follow a test example with and without JFaker:

imagine you be testing a class who maps some object to another

code example without JFaker (fixed data)

// configuraçoes da sua classe com sua lib de testes
void mapTest(){
    var entity = new UserEntity();
    entity.setId(1);
    entity.setName("name");
    var dto = testClass.toDTO(entity);
    //asserções do seu código
}

code example with JFaker (with random data to make your test more dynamic)

// configuraçoes da sua classe com sua lib de testes
void mapTest(){
    var entity = UserEntityBot
        .builder()
        .build();
    var dto = testClass.toDTO(entity);
    //asserções do seu código
}

The best part about this is who the UserEntityBot class is generated each time you will do a build using a simple configuration

Starting with JFaker

Make a follow steps

1- For use JFaker in your project, just add a follow dependencies:

JFaker use a Datafaker lib in bots for generate random data ( for more informations how Datafaker works here have a link for Datafaker's documentation)

2 - Extends a class net.datafaker.Faker from Datafaker lib and we will start a configure your bots

//imports

@FakerInfo(
    botsConfiguration = {
        @AutoFakerBot(
            generatedInstance = "br.com.sample.UserEntity",
            packageToGenerate = "br.com.sample.bot",
            botBuildStrategy = @BotBuildStrategy(
                setterStrategy = @SetterStrategy
            )
        )
    }
)
public class MyCustomFaker extends Faker {

}

In a previous code we say to generate a bot for UserEntity class in a package br.com.sample.bot and the bot will input data using setters class method.

Now you are ready to use your UserEntityBot who will have a code looks like a follow code:

// imports omitidos
public class UserEntityBot extends AbstractBot<UserEntity> {
    private MyCustomFaker faker = new MyCustomFaker();

    private Supplier<Long> id = () -> (long) faker.number().positive();
    private Supplier<String> name = () -> faker.lorem().word();

    public BookModelBot withId(final Supplier<Long> id) {
        this.id = id;
        return this;
    }

    public BookModelBot withName(final Supplier<String> name) {
        this.name = name;
        return this;
    }

    public BookModel build() {
        var userEntity = new br.com.sample.UserEntity();
        userEntity.setId(id.get());
        userEntity.setName(name.get());
        return userEntity;
    }
}

Is possible to populate your instance using other strategies (check in a documentation a section where we say about @BotBuildStrategy )

How you looks like our bot allow to define a fixed data for tests where we need some specific information in a class property, for this we use a with methods

All generated bots by defaul extend a class AbstractBot to provide some methods. A build method without arguments for create a single instance with random data and a overload who receive a long argument and generate a list with X instances, where X is a number input in build argument ( for more informations about AbstractBot class click )

@kingthorin
Copy link
Collaborator

See also:

@juniorjrjl
Copy link
Author

that is cool! I don't knew about this. But my idea is litle different, this annotation is used in runtime, my project use annotation processor to generate bot class, you don't need annotate model class and "dirty" it, annotation processor will generate a class to build instances and allow you configure providers for each class properties, create extensions for generate your bot and store it in a database ( for exemple).
I thing many things to make project very extendable and flexible, but thank you for space to show it :)

@bodiam
Copy link
Contributor

bodiam commented Jul 2, 2024

That's great @juniorjrjl , thank you for sharing! What's your intention with JFaker? Do you want to keep it a separate project and use Datafaker as a potential data provider? Or would you consider a tighter integration between the 2? I think we would be open to any kind of approach, and if we should make changes to make JFaker + Datafaker easier, let us know, happy to discuss!

@snuyanzin
Copy link
Collaborator

Thanks for sharing this

But my idea is litle different, this annotation is used in runtime, my project use annotation processor to generate bot class, you don't need annotate model class and "dirty" it, annotation processor will generate a class to build instances and allow you configure providers for each class properties, create extensions for generate your bot and store it in a database ( for exemple).

we were thinking about similar approach however we faced a couple of limitations

  1. How to generate an object with different locale
  2. How to generate an object with different seed
  3. How to generate several different objects (one with Japanese locale and seed 1, another with Japanese locale and seed 10, the third one with French locale and seed 10 and the fourth one with French locale and seed 1000)?

How do you solve this with such configuration?

@juniorjrjl
Copy link
Author

@bodiam I think about integration is good, I believe this suggest have a great potential and could be very interesting to help a create tests were developer write less code to generate object instances and care more about tests's scenary.

@juniorjrjl
Copy link
Author

@snuyanzin about your questions

1 I my actual code I didn`t think about, but I think it's possible make some changes

// imports omitidos
public class UserEntityBot extends AbstractBot<UserEntity> {
    private MyCustomFaker faker = new MyCustomFaker();

    private Supplier<Long> id = () -> (long) faker.number().positive();
    private Supplier<String> name = () -> faker.lorem().word();

    public BookModelBot withId(final Supplier<Long> id) {
        this.id = id;
        return this;
    }

    public BookModelBot withName(final Supplier<String> name) {
        this.name = name;
        return this;
    }

    public BookModel build() {
        var userEntity = new br.com.sample.UserEntity();
        userEntity.setId(id.get());
        userEntity.setName(name.get());
        return userEntity;
    }
}

this code is a class example generated by my code, for solve this problem we could change a moment where faker instance is created (instantiate in build method for example) and pass a locale by param

2 - In this code is possible, all generated bots extend a class AbstractBot, but is possible configure bots to use another class, you need create a another class inherits AbstractBot and put in this class a method who returns a bot instance after save it on database, I create a wiki in this repository explain some resources https://github.com/juniorjrjl/jfaker/wiki (sorry if my english is bad in this wiki) and in this topic have a solution of this question https://github.com/juniorjrjl/jfaker/wiki/9---Customize-your-Bots

3 - For this we need think about faker object is instantiate ( like I explain in answer 1)

this code is a first version, We can think about improve it and include more features.

@snuyanzin
Copy link
Collaborator

thanks for explanation
i was asking since all 3 cases are now covered by datafaker existing functionality and locale/seed should be just specified via annotation or method call (both are possible)
no need for other changes

@bodiam
Copy link
Contributor

bodiam commented Jul 14, 2024

Is any action required for this ticket?

@snuyanzin
Copy link
Collaborator

i don't think so
i would consider it like FYI

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants