Skip to content

Instantiator for Scala. Give me a type and I give you an instance of it!

License

Notifications You must be signed in to change notification settings

pepegar/instantiator

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

56 Commits
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

instantiator

Build Status

Instantiator is a library that comes to help you testing your Scala code. It is able to instantiate any scala class with just a line of code:

import com.pepegar.Instantiator

class MyClass(paramOne: Int, paramTwo: String)

val myInstance = Instantiator.createInstance[MyClass]

But that is not the best point of Instantiator. It can create instances of really big classes, for which creating a generator would be a pain in the ass. For example, take a look at the following classes, particularly HellOnEarth :

import com.pepegar.Instantiator

case class A()
case class B()
case class C()
case class OtherClass(a:A, b: B, c: C)
case class HellOnEarth(
	a: Int,
	b: String,
	c: Double,
	d: OtherClass,
	e: A,
	f: B,
	g: C,
	h: Int,
	i: String,
	j: Double,
	k: OtherClass,
	l: A,
	m: B,
	n: C,
	o: Int,
	p: String,
	q: Double,
	s: OtherClass,
	t: A,
	u: B,
	v: C,
	w: Int,
	x: String,
	y: Double,
	z: OtherClass
	)

val superShinyObject = Instantiator.createInstance[HellOnEarth]

And that's it, you have a perfect superShinyObject that you can pass around in your tests.

How it works?

Instantiator uses the Scala reflection API to inspect the types of the properties and then generates random data for them based on their types.

First of all, it generates a Types tree based on the classname you pass to createInstance. In charge of generating the Types tree is the TypesTreeMaker trait

After that, we generate random values for that types using the Scala Random API. That is done by the TypesToValuesMapper trait.

The last step in the process is parsing the Values tree to get the instance of the class. It is done in the ValueTreeParser trait

All these traits are mixed into the Instantiator object, which is the entry point of the library.

Restrictions

  • Right now, Instantiator will use the first constructor it will found, so it's better not to try to instantiate classes with more than one constructor.

  • It is not tested against collections. I don't know what approach to follow in the number of elements to generate for the collection. Probably a random integer from 1 to 100 would be enough.

  • Type erasure. In the JVM, type parameters are erased at compile time, and this library runs at runtime. What the f*ck can I do with that? I mean, it is possible to kind of infer the inner type of any parametric data type by inspecting one element of it and getting its type. However, that raises two more questions:

    • The type of that element may lead you to a wrong type, for example:
    val a: List[Any] = List(1)
    

    if we inspect the type of the element in the list, we can think that this list would be a List[Int], or a List[Number]... Noooope.

    • I don't know any element of the parametric data type BECAUSE IS MY JOB TO GENERATE IT...

Acknowledgements

I started this project while at h4ckademy, the best educational experience in my life.

License

see LICENSE

About

Instantiator for Scala. Give me a type and I give you an instance of it!

Resources

License

Stars

Watchers

Forks

Packages

No packages published

Languages