Replies: 3 comments
-
I like this idea. But maybe something slightly more lightweight would suffice:
Of course, this still relies on a bit of social convention; it would still be technically possible to import |
Beta Was this translation helpful? Give feedback.
-
Actually, another viable technique could be to use |
Beta Was this translation helpful? Give feedback.
-
I actually like the Consider |
Beta Was this translation helpful? Give feedback.
-
I'm exploring how to write tests for individual functions without having to expose public access to them. I'm thinking about this problem with respect to functions that have privileged access to internal state, which would break encapsulation and perhaps allow users to accidentally violate invariants if they were to be called in inappropriate contexts.
Here's a few links I came up with when googling:
Most resources seem to suggest using a "social convention", with modules named
*.Internal
.I wonder if, instead, there is a technical means to enforce the convention.
Take the function
addRobot
. Excepting for one usage here and another questionable usage in #1372, perhaps that function could be removed from the export list of theState
module to discourage its use in the wrong context.However, the
addRobot
function is also referenced outside of the game in theTestUtil
module. Could we somehow still test this function while also removing it from theState
module's export list?A "Testable" smart constructor
Define a type in a module named
TestFramework
:and only export the
makeTestable
function, not theTestable
constructor.In the
State
module, define:Then export the
addRobotTestable
function, but not theaddRobot
function, from theState
module.The
TestFramework
module has exclusive access to the contents of theTestable
newtype. However, tests for theaddRobot
function cannot be written in theTestFramework
module, because referencing theaddRobotTestable
function exported fromState
would entail a circular dependency.But instead, maybe the
TestFramework
module could also export a monad that facilitates testing...A "Testing" monad
Could we define a
Reader
monad namedTesting
, and then use it to access members ofTestable
? Then maybe the only way to access theaddRobot
function outside of theState
module would be to run theTesting
monad. But that monad would "pollute" the context in which it is run, so the only way in practice to execute theaddRobotTestable
function would be inside some dedicated testing framework?I have not written code to prove this concept.
Beta Was this translation helpful? Give feedback.
All reactions