Mmm…, I don’t know how to start this post, actually, it’s not about Leetcode but about my laziness (yes, very similar to the story about git naming).
I’m practicing my algorithm skills with Leetcode and I’m a lazy coder on every aspect. This time is about writing test cases for testing my code. For instance, let’s get the question #7. Reverse Integer as an example. After writing a solution like this:
intmax = 2 ** 31 - 1
intmin = -2 ** 31 is_positive = x >= 0
x = abs(x)
result = 0
while x > 0:
pop = x % 10
pop = pop if is_positive else -pop
x //= 10
result = 10 * result + pop if result > intmax or result < intmin:
I would usually write test code like this
When the number of test cases reaches 5 or more, it’s hard to recognize which result goes with which input (yes, we have to move the eye from console to the code editor).
For solving parameters vs result problem, I came up with a simple solution:
def test(fun, *params):
print params, fun(*params)
and the test code would be:
test(sol, 1) # 1 1
test(sol, 12) # 12 21
test(sol, 123456789) # 123456789 987654321
Easier, right? Yeah, but not so good. Firstly, I have to repeat
test and also
sol every time a new test case added. I’m lazy and I don’t accept that. Secondly, the output is messive. I don’t like this mess.
The second problem is easier to fix with just a little effort for formatting.
def test(func, params, expected=None):
format = '%10s ' * len(params)
param_text = format % params
result = func(*params)
if expected is not None:
correct = result == expected
print "%s --> %-10s | %s" % (param_text, result, correct)
print "%s --> %s" % (param_text, result)
With this solution, I added the expected value to check whether the test case result was correct but I still have to repeat
sol . Besides, there is a hardcoded value for formatting parameters:
%-10s . What if the parameter is very long or very short? Not so good at all. We are only able to solve the hardcoded problem only if we know all the parameters of all test cases before printing out the result.
def test(func, testcases):
The above code was an idea in my mind. However, it has never been implemented because I then recalled Python’s
decorator . Here is my final solution:
and my test code will be:
(1, 1), # (expected_value, param0, param1,...)
return ysol() # <--- I want to remove this too
Update April 2:
Finally, I could remove the last method call on the above sample code which I intended to remove
sol() # <--- I want to remove this too
testcase is here. I also added
log() for printing debug logs during testing.
After using this, I just need to add
@testcase(...) and then hit run. No more
sol() call. I also added a configuration for autorun a method or not in case we implement more than a solution within a file.