But past that it will balloon and just bloat the program you're trying to understand. Tests are better left in their own file. That's not to mention test infrastructure (mocks etc) should you need it.
But past that it will balloon and just bloat the program you're trying to understand. Tests are better left in their own file. That's not to mention test infrastructure (mocks etc) should you need it.
To add to what you said, this is exactly the kind of situation where we design features that _may_ not scale well, but are remarkably useful in teaching contexts.
Having test cases inline with code is massively useful:
1. For students not used to thinking about their program being split over several files. If tests must be in their own file, then understanding multi-file programs (modules, essentially), becomes a curricular dependency of writing tests. That is a _lot_ of friction early on – think about an intro student who has a fuzzy notion of a "working directory" or IDE "workspace" in general. Even if the eventual goal is to address these concepts, they shouldn't have to come first just to write a unit test.
2. When live coding in front of a class. Having tests in a separate file is a huge pain because you pay either (a) the cognitive overhead of switching buffers, or (b) precious projector real-estate on having both open. Since live-coding programs that are less than 100 lines long is a major use case for Pyret, this is a big win.
As programs scale up, for example in Pyret's compiler or in larger assignments, we end up with a blend of test cases in inline where: blocks, with the majority in separate files in standalone check: blocks. So at scale, things turn into more traditional-looking separate suites.
Also, mocks are arguably a test-code-smell side effect of too little isolation: https://www.destroyallsoftware.com/blog/2014/test-isolation-...
In my Elixir one-page code experiments, I put the unit test in the same file after the code under test. It makes sure the test only runs when the file is loaded a certain way: https://github.com/pmarreck/elixir-snippets/
However, for educational purposes, I think it's actually a compelling idea. My perspective is that while unit tests are a great idea, each unit test only provides marginal value. Thus, unit tests need to be as easy and natural to write as possible or developers won't do it.
Habits, like writing code that doesn't need much mocking, definitely makes TDD easier, but that often comes after habituating oneself to TDD. For students, I think getting them as early as possible to write unit tests would be a big win. Putting the tests right there in the code with no need to set up test infrastructure or learn a separate test framework will be helpful.
What we find valuable is to write a _small_ number of _illustrative_ examples, which we call the “sweep”, that summarize the main behavior of the function. Think of it as essential, runnable documentation. When you come to a new codebase (including your own, six months later!), these help you quickly page back in what the function was supposed to do.
The sweep is also really useful for peer-review, which is another especially valuable technique in both education and industry. We have done some nice studies on its effectiveness: http://cs.brown.edu/~sk/Publications/Papers/Published/pcgfk-...
I like the idea of short functions with doctest-like tests, but written with the real language, syntax-highlighted, etc. In addition to education, it's good for quick prototyping. It's also nice to see at a glance which functions don't have tests!
But I can also see it getting a bit unwieldy for complicated stuff, so in that case you can put it in another file, perhaps with a pointer.
I'm guessing you can't stop people from writing tests in separate files, so I suppose Pyret allows that.
I guess you could write a unit test framework in Python that does this with a tiny amount of metaprogramming.
def Foo():
return 5
def testFoo(t):
t.assertEqual(Foo(), 5)
So you could just look for all the functions in the file named "testFoo" where Foo is also a function, and then run them with the "t" param. Hm.In D there is even a keyword for that. It allows to embed the tests into the documentation as examples. This has the nice side effect that your examples are actually tested. https://dlang.org/spec/unittest.html