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

Generating objects for combination approval tests #232

Open
ragunathjawahar opened this issue Jan 13, 2022 · 7 comments
Open

Generating objects for combination approval tests #232

ragunathjawahar opened this issue Jan 13, 2022 · 7 comments

Comments

@ragunathjawahar
Copy link
Contributor

Folks, curious to find out if there's a way to do this with Approvals or a different 3rd party library. I checked the public APIs, I wasn't able to find anything. I found a function 9 variation but not the others.

I have an object with x number of parameters and there are y number of objects. How do I generate inputs for them to use with combination approvals. For instance,

My classes

data class Coffee(
  val estate: String,
  val roast: Roast,
  val grindSize: GrindSize
)

enum class Roast {
  Light, Medium, Dark
}

enum class GrindSize {
  Fine, MediumFine, Medium, Coarse
}

Expected

Coffee(estate = Attikan, roast = Light, grindSize = Fine)
Coffee(estate = Attikan, roast = Light, grindSize = MediumFine)
Coffee(estate = Attikan, roast = Light, grindSize = Medium)
Coffee(estate = Attikan, roast = Light, grindSize = Coarse)
Coffee(estate = Attikan, roast = Medium, grindSize = Fine)
Coffee(estate = Attikan, roast = Medium, grindSize = MediumFine)
Coffee(estate = Attikan, roast = Medium, grindSize = Medium)
Coffee(estate = Attikan, roast = Medium, grindSize = Coarse)
Coffee(estate = Attikan, roast = Dark, grindSize = Fine)
Coffee(estate = Attikan, roast = Dark, grindSize = MediumFine)
Coffee(estate = Attikan, roast = Dark, grindSize = Medium)
Coffee(estate = Attikan, roast = Dark, grindSize = Coarse)
@LarsEckart
Copy link
Contributor

LarsEckart commented Jan 13, 2022

How about this:

import org.approvaltests.combinations.CombinationApprovals;
import org.junit.jupiter.api.Test;

public class CoffeeTests {

  @Test
  void testAllCombinations() {
    String[] estates = new String[]{"Attikan", "Other"};
    CombinationApprovals.verifyAllCombinations(this::applesauce, estates, Roast.values(),
        GrindSize.values());
  }

  private String applesauce(String estate, Roast roast, GrindSize grindSize) {
    Barista barista = new Barista();
    Coffee coffee = new Coffee(estate, roast, grindSize);
    return barista.make(coffee);
  }

  class Barista{

    public String make(Coffee coffee) {
      return "preparing ... " + coffee + " ... done";
    }
  }

  record Coffee(
      String estate,
      Roast roast,
      GrindSize grindSize) {
  }

  enum Roast {
    Light, Medium, Dark
  }

  enum GrindSize {
    Fine, MediumFine, Medium, Coarse
  }

}

@ragunathjawahar
Copy link
Contributor Author

ragunathjawahar commented Jan 13, 2022

Right, this works for simple objects and I use this. What happens when one of the input values to verifyAllCombinations is a List<Coffee>, List<Location>, and List<Cafe>. And each of these objects have 3, 4, 5 properties each? That would total to 12 parameters and verifyAllCombinations takes in 9 parameters at most. If I am not wrong.

@LarsEckart
Copy link
Contributor

ah, so you rather have a separate Combinator and the result of that as 2nd argument then?

List<Coffee> listOfAllCombinations = whatYouWant(String type, Roast roast, List<Ingridient> ingrediants ....);
CombinationApprovals.verifyAllCombinations(this::applesauce, listOfAllCombinations);

@ragunathjawahar
Copy link
Contributor Author

I wrote a simple class that can do this at the moment,

val coffee = ObjectStream
  .of(Coffee::class)
  .property("estate", "Attikan")
  .property("roast", Roast.Light, Roast.Medium, Roast.Dark)
  .property("grindSize", GrindSize.Fine, GrindSize.MediumFine, GrindSize.Medium, GrindSize.Coarse)
  .generate()

coffee.onEach(::println)
Coffee(estate = Attikan, roast = Light, grindSize = Fine)
Coffee(estate = Attikan, roast = Light, grindSize = MediumFine)
Coffee(estate = Attikan, roast = Light, grindSize = Medium)
Coffee(estate = Attikan, roast = Light, grindSize = Coarse)
Coffee(estate = Attikan, roast = Medium, grindSize = Fine)
Coffee(estate = Attikan, roast = Medium, grindSize = MediumFine)
Coffee(estate = Attikan, roast = Medium, grindSize = Medium)
Coffee(estate = Attikan, roast = Medium, grindSize = Coarse)
Coffee(estate = Attikan, roast = Dark, grindSize = Fine)
Coffee(estate = Attikan, roast = Dark, grindSize = MediumFine)
Coffee(estate = Attikan, roast = Dark, grindSize = Medium)
Coffee(estate = Attikan, roast = Dark, grindSize = Coarse)

I want to make sure that I am not wasting my time reinventing the wheel here. Thoughts?

@ragunathjawahar
Copy link
Contributor Author

This way I can configure each individual object and pass them down stream to verifyAllCombinations 🤔

@ragunathjawahar
Copy link
Contributor Author

More concrete example, how do we bring functions like these under test, when we have more than 9 input parameters. Assignment and Briefing themselves are complex objects. Combination approvals could work here, but it would hit the limits when we have more complex objects.

@ragunathjawahar
Copy link
Contributor Author

ragunathjawahar commented Jan 23, 2022

@LarsEckart and @isidore, curious to find out if I am missing something obvious here. If yes, can you folks point me in the right direction?

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

2 participants