-
Notifications
You must be signed in to change notification settings - Fork 12
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Feature request: run tests and write results as expected output #69
Comments
Well, prepare to switch. If you don't specify something that you "want", then it wont compare it. Alternatively, if you really want to specify a "want" string, you can add For example: >>> print('hi') passes >>> print('hi')
hello fails >>> # xdoctest: +IGNORE_WANT
>>> print('hi')
hello passes There is one feature that doesn't currently exist that might make this even simpler. Currently BTW, you can hack this by using |
Also note that in terms of dealing with minor repr issues is the reason I wrote ubelt.repr2, which strives to make a consistent and deterministic output between all python versions. For random seeds, I strongly recommend using a I use these previous two techniques quite a bit, but when they fail I fall back on |
Imagine we have a doctest like the following: >>> date.today().year
2020 This is fine for this year, but next January I would like to be able to run a command like This is a contrived example, obviously, but I always want my example outputs to be checked (the opposite of
I was thinking more of intentional updates, such as adding a new attribute to an object. I agree that seeding your PRNG is essential, but I still often need to change by doctest outputs when e.g. I change a function in some simulation code and it calls It's things like this, where even seeded random results are very very sensitive to code changes, which would make a zero-effort update command so useful 🙂 As-is, I've just had to avoid using doctests for any output that I expect might change because having example outputs in our docs just isn't worth the trouble. |
So my feeling on intentional updates is that its a normal part of code maintenance. If you update the code in a way that modifies behavior or adds an additional attribute, it seems reasonable that part of that update would also involve making changes to tests. Either that, or tests could be written in such a way that they only check that expected components of the output exist, and allow new components to pass through. I've certainly encountered this problem before, but I haven't felt a dire need to automate this part of the development cycle. I'm worried about two cases:
My doctest: Example:
>>> # xdoctest: +REQUIRES(module:ndsampler)
>>> from netharn.metrics import DetectionMetrics
>>> dmet = DetectionMetrics.demo(
>>> nimgs=10, nboxes=(0, 10), n_fp=(0, 1), n_fn=(0, 1), nclasses=3, cls_noise=.2)
>>> cfsn_vecs = dmet.confusion_vectors()
>>> cm = cfsn_vecs.confusion_matrix()
>>> print(cm.to_string(float_format=lambda x: '%.2f' % x))
pred background cat_1 cat_2 cat_3
real
background 0 1 1 1
cat_1 2 12 0 1
cat_2 2 0 14 1
cat_3 1 0 1 17 failed because I had changed the output from integers to floats, so it wanted a bunch of Therefore, if I had auto-changed the "want" string to what the doctest "got", I would have had this mess: Example:
>>> # xdoctest: +REQUIRES(module:ndsampler)
>>> from netharn.metrics import DetectionMetrics
>>> dmet = DetectionMetrics.demo(
>>> nimgs=10, nboxes=(0, 10), n_fp=(0, 1), n_fn=(0, 1), nclasses=3, cls_noise=.2)
>>> cfsn_vecs = dmet.confusion_vectors()
>>> cm = cfsn_vecs.confusion_matrix()
>>> print(cm.to_string(float_format=lambda x: '%.2f' % x))
submit assign detection jobs 10/10... rate=55315.55 Hz, eta=0:00:00, total=0:00:00, wall=12:47 EST
assign detections 10/10... rate=2743.98 Hz, eta=0:00:00, total=0:00:00, wall=12:47 EST
ndarray convert 9/9... rate=53693.84 Hz, eta=0:00:00, total=0:00:00, wall=12:47 EST
pred background cat_1 cat_2 cat_3
real
background 0.00 1.00 1.00 1.00
cat_1 2.00 12.00 0.00 1.00
cat_2 2.00 0.00 14.00 1.00
cat_3 1.00 0.00 1.00 17.00 (Also the doctest would also fail again, because a timestamp appeared in the "want" string) Instead of the desired: Example:
>>> # xdoctest: +REQUIRES(module:ndsampler)
>>> from netharn.metrics import DetectionMetrics
>>> dmet = DetectionMetrics.demo(
>>> nimgs=10, nboxes=(0, 10), n_fp=(0, 1), n_fn=(0, 1), nclasses=3, cls_noise=.2)
>>> cfsn_vecs = dmet.confusion_vectors()
>>> cm = cfsn_vecs.confusion_matrix()
...
>>> print(cm.to_string(float_format=lambda x: '%.2f' % x))
pred background cat_1 cat_2 cat_3
real
background 0.00 1.00 1.00 1.00
cat_1 2.00 12.00 0.00 1.00
cat_2 2.00 0.00 14.00 1.00
cat_3 1.00 0.00 1.00 17.00 Note that xdoctest's got/want check only verifies the trailing outputs lines, so the That being said, its a reasonable use case, and code that writes code is something I'm generally into. I'm not against giving the user the tools to shoot themselves in the foot, although I would want to clearly document that something like this would have that capability. I don't think I would want to implement this myself, but I'd probably accept a PR if you wanted to take a shot at it. Each DocTest object (defined on xdoctest.doctest_example.DocTest), knows the file (self.modpath) and line number (self.lineno) that the doctest beings on, and contains a list of xdoctest.doctest_part.DoctestPart objects (self._parts). Each DoctestPart contains |
FYI, I'm warming up to this idea. I've experienced several cases where it would have been useful. I might implement it. I'll comment if I start on it, so anyone else who wants to have a go at it feel free to get to it before I do. |
I'm actually very warm 🔥 on this idea. I actively want it. I've been fixing pytorch's doctests and having this would have saved a ton of time. I hacked in an experimental feature that adds a +SKIP directive to every failing test. Handling this feature should only be slightly more involved than that. Would just need to find the lines corresponding to the "WANT" and replace them with the "GOT" string, which should be stored in the doctest's member variables. xdoctest/src/xdoctest/runner.py Line 341 in 6af2790
|
The most annoying thing about doctests is having to manually update them all when something changes the repr of your outputs, or a random seed, etc. If there was an
xdoctest
mode which wrote the output instead of comparing it, I'd switch over tomorrow 😀The text was updated successfully, but these errors were encountered: