Loading collection data...
Collections are a way for you to organize kata so that you can create your own training routines. Every collection you create is public and automatically sharable with other warriors. After you have added a few kata to a collection you and others can train on the kata contained within the collection.
Get started now by creating a new collection.
yes, you totally got my idea. Only do a "end check".
About the branching, yes, you're right. To keep that part of the requirements I'd have built andother kind of function/procedure that would build a chain, store the result, then build several other chains coming from it and check the final result (I guess you can do that with one single function and a/some default argument(s)).
Maybe somethign like:
That's roughly what I'd try to achieve, I believe. Not saying it's better. Just another approach.
Right. Yes that would be super silly! That's not what I'm doing. And you should totally be shutting me down if that was the intention. Not worth it in the slightest.
If you look at the test output, it isn't linear. I am making random attacks on the available operations existing on the mutable state.
now you have my interest. what do you mean that you would do instead?
do you mean that, for this specific kata, you would just make all the calls and check the end result? I think you'd miss a few test requirements then but I'm also speculating about what you mean x)
I'd argue there's no exception handling :D There's a super-break, and there's a log dump. Nothing delicate or clever.
Right so you do mean, just fire off the linear calls all at once. BUT we actually need to treat it more like a tree and test different branches. And they can't be explored separately in isolation, because there is good reason to test them together to see that they do not affect one another. For example, it should be possible to call it five times, save the result, and then call that result with different inputs (branching). A BIG problem here is mutable state, without that, yeah, it could be a single check for a long chain of calls. Same with the user print debugging - they may need to know everything that was done, a straight path to where the problem happened might not reproduce it because of mutable state. I would for example not need to print out the assertions I made if not for the fact that they can mutate state when using
==
(as stupid as that is, clearly everyone should move over to haskell and abandon all else)You don't see me writing these for function-kata's, because they start over with fresh state on each invocation, and anything they do internally is none of my business. Good!
Am I spoon feeding? Yeah.. no.. maybe? I'll complain about mutable state here again. It can be real tricky figuring out what was done. What I am in particular aiming for is reproducability. Think of all the "works in my IDE" posts.
The user should never need to question the test code, they should be shown what happened. I think that's fair, not spoonfeeding? :D
Am I done with it? So, just like with message posts I have a terrible habit of editing things after submitting. I think I'm through with that though, yeah.
Not sure. If I had to deal with this, adding logs "somewhat like you did", I'd actually avoid the step by step testing/logging. This reduces a lot the amount of code needed and it's complexity: no need for var names anymore, no need for the extra layer of exception handling (the deepest one in
run_scenario
), and you still can give all the steps to the user.The extra layer of information about "when" the user's code is failing in the sequence is nice, but imo you're a bit spoon feeding the user: in most cases, if something must go wrong, it will be on the second or third call (Im talking about exceptions). Depth being rather low, the user can debug that rather easily with print stuff.
btw, I got caught in the discussion and just forgot: we're good to go about approval, so? Or do you want to change some stuff yet? (on my side, green flag)
Do you think simpler code could produce the same/equivalent input?
It's doing .. three things, right?
Calculating the expected result - same as the solution.
Logging.
Testing.
These always happen in sync. So - bundle them up into a single thing to avoid possibility of desynchronization.
Maybe this bundling could be defined differently.
Yup!
Or call the
grumpyFace
variable or whatever. ;)Right but that comes from trying to re-raise when there is nothing to re-raise. :D
You may as well divide by zero.
You're not raising nothing, you're failing to raise and therefore python will raise a RuntimeError
actually there is (sort of): if you type just
raise
, you actually raise an error (telling you this code cannot execute, but still x) So Stuff like this is usable (but bad, yeah)::)
(but I guess that's a bad habit I got since I started JS... :( )
Right so that IS re-raise. There is no such thing as bare raise.
Also I'm changing to this:
I previously used a linter that would complain about this but ... tbh I think that's misinterpretation of pep8 which says to be specific/narrow. But I specifically want to catch everything there. :P
oh, you actually just taught me something I didn't know about python... XD
Uh. But to be clear, both
raise
andraise e
have the exact same effect and all you're talking about here is that you prefer one syntax over the other?"bare raise" sounds a whole lot like something similar to raising a string in javascript, except, raising, but nothing. but it's a re-raise so bare sounds like what would happen if you type
raise
in python's repl, causing a RuntimeError since there is nothing to re-raisereturn -> break I'm okay with. yeah I thought you wanted to avoid exceptions as flow control
but this would be the exact same exception pattern/amount
yes I saw. ;)
No. Because I believe you're not talking about the same one I did.
afaik, nope either ;)
Code is simpler than sentences, so here is what I suggested:
clearer now?
There's bound to be a quote somewhere about tests inheriting the complexity of the thing they're testing, I can feel it in my left ring toe.
The exceptions.. those are two mostly unrelated things.
AssertionFailed
could be replaced by break, sure, yeah. Is that an improvement? I would have to thread the comparison results out of the actions. Having that super-break is awfully convenient and I don't think it's all that offensive or even unidiomatic. I am asserting stuff after all, bailing out is implied.The user exceptions I simply let through. I think when you say
bare raise
you mean something else because that is a re-raise.I wouldn't dream of messing with the user's exception, all I want from it is to know it happened so that I can dump the log.
well, the least we can say is that you don't like when things are simple... XD
why(edit: forget that, I just forgot to read the 3 next lines... x) )acc = add
? I mean, why not just use add directly? (solution of the user)I'd rather use this at the very end of
run_scenario
(that way, you can usebreak
instead of return and raise in the loop. It's doing the same than your code, but no exception thrown (about that: if you keep the raise, reraise the original exception, don't use a bareraise
) on the user side):note: on second thoughts, it might be better to reraise the exceptions...
note2: the
for/else
construct is a good indication to the reader that this statement will only execute if the loop succeeds. So it could be a good addition, to hint the logic without having to read the content of the loop. But nothing mandatory here.cheers
This comment is hidden because it contains spoiler information about the solution
Loading more items...