Best practices for rholang unit tests
Does anyone have ideas for the best way to unit test rholang code?
So far I've seen https://github.com/rchain/rchain/blob/dev/rholang/examples/linking/v0.1/tests/IMap_test.rho which is a good start, but almost no-one knows how to run the linker.
As far as I know the only unit testing for Rholang which is being used today is TestSet.rho which is modeled after ScalaTest. The idea is you have some plain English description of what is supposed to happen and then a series of tests that show this occurring. The tests are specified as pairs `(name, answer)`, where `name` is expected to be a channel on which another name is being sent and that name in turn has a listener (`for`) which is waiting for a single return channel to be sent and it is expected that `answer` will come back as a message on that return channel. The reason for this somewhat convoluted design is to balance between being generic and still useful. For examples of using TestSet see EitherTest.rho, NonNegativeNumberTest.rho, MakeMintTest.rho, BasicWalletTest.rho.
I don't know whether or not this should be considered a "best practice", but it is the only one that I am aware of. I would be happy to hear about improvements people have on this model, or about what others are trying themselves.
One nice thing about this is that it integrates reasonably well into the RChain core dev team's existing unit testing pipeline, so these tests do not need to be run separately. This is done via TestSetUtil.scala and you can see examples of how this is used in EitherSpec.scala, NonNegativeNumberSpec.scala, MakeMintSpec.scala, and BasicWalletSpec.scala.
In regards to the linker, I'll mention here that all these examples also have dependencies which in principle would need to be "linked". However, following the advice of Kyle Butt, the way we view dependencies now is to assume that they are already loaded into the tuplespace as opposed to creating a single large contract which loads everything itself. This is similar to the recommended way of addressing dependencies in the JVM world; individual jars are all included on the classpath instead of a single "fat jar". Of course, unlike Java, Rholang does not throw any error when you try to access a missing dependency, instead just the message is stored in the tuplespace until the dependency is loaded. That being said, there will likely be a proper package manager some time in the future (like a few years from now).