vincent-hugot / qtest

Inline (Unit) Tests for OCaml
GNU General Public License v3.0
67 stars 8 forks source link

How to oversome the fact that a .mli file can hide some things to qtest? #24

Closed UnixJunkie closed 8 years ago

UnixJunkie commented 8 years ago

Currently, in a hurry, I just removed the corresponding .mli file so that qtest can see everything from the .ml file, even types which are not exported to the .mli.

vincent-hugot commented 8 years ago

Short answer: you can't. QTest deals with with the interface actually given to the user, full stop.

In some cases, you can get away with using code injection -- e.g. if it's just a private function -- but it becomes hairy for types. You may end up having to inject all of your module's private code.

That's probably the most-discussed -- dare I say "controversial" ? -- aspect of qtest's current design, in particular with @gasche. See for instance this, "# Ambitious proposal 8".

edit: I'd recommend exporting what you need, clearly marked and documented as "internal, warranty void etc".

UnixJunkie commented 8 years ago

Yeah, my use case was just that: "test private functions that are not published through the module interface". I could get away by just erasing the .mli file from my checkout but hoped this would just be a temporary hack.

vincent-hugot commented 8 years ago

If it's just a simple private function that uses public types only, you can do a copy-inject:

(*${*) code (*$}*)

that code is shared by the module and the test module. If it's your function, then you should be able to test it.

See https://github.com/vincent-hugot/iTeML/blob/master/qtest/tests/foo.ml around l80 for a toy example of a module with tests on internal stuff, using those injection pragmas.

In more complicated cases, it won't be enough.

UnixJunkie commented 8 years ago

Can I put the whole code of the module up to the unit tests between those qtest tags?

vincent-hugot commented 8 years ago

You can.

Will it work ? I don't know -- that's not the problem injection was supposed to solve, and I haven't touched qtest (or Caml) since I wrote qtest, so I don't remember how things work well enough to predict how that hack might work. You'll have to try and find out. If you inject the needed types, it's worth a shot, assuming you're not in a functor.

I'd still recommend (what I view as) the sensible approach of skipping the headache and exporting just what you need to for the tests you need to do, with proper documentation to discourage abuse.

UnixJunkie commented 8 years ago

The hack works:

(*${*) code (*$}*)

Just, don't forget to use the closing tag before your unit tests. :)

UnixJunkie commented 8 years ago

Super cool!

vincent-hugot commented 8 years ago

Heh, good to know!

Thanks for the feedback.