-
Notifications
You must be signed in to change notification settings - Fork 220
Codewars Python Test Framework
Blind4Basics edited this page Jan 6, 2018
·
17 revisions
test.describe("Example Tests")
test.it("Example Test Case")
test.assert_equals(add(1, 1), 2, "Optional Message")
print("<COMPLETEDIN::>")
print("<COMPLETEDIN::>")
- Checks that the actual value equals the expected value.
- Checks that the actual value does not equal the expected value.
- Checks that
function
throws something.
- Checks that
passed
is truthy. Note that the test suite will continue its execution if the keywordallow_raise
isn't manually set toTrue
. - You should absolutely avoid the call toe
test.expect
without the message argument because it won't give any feedback about the reason why the assertion failed. - So, provide an useful
message
!
In Python, the Test.describe
and Test.it
will concatenate themselves if you do not use this element to close the blocks. Note that the statement will not show up in the console.
Test.describe("1")
Test.it("A")
Test.describe("2")
Test.it("B")
Test.it("C")
Leads to:
1
A
2
B
C
Test.describe("1")
Test.it("A")
print("<COMPLETEDIN::>") # <- close it
print("<COMPLETEDIN::>") # <- close describe
Test.describe("2")
Test.it("B")
print("<COMPLETEDIN::>") # <- close it
Test.it("C")
print("<COMPLETEDIN::>") # <- close it
print("<COMPLETEDIN::>") # <- close describe
Leads to:
1
A
2
B
C
- Fixed tests first.
- Use all your
example tests
at the beginning of thetest cases
. - Create enough fixed tests so that it would be "more boring" to store/hardcode their results than to implement the needed code.
- Implement random tests
- Never define utility methods (such as your internal solution!) at the beginning of the test cases: this way it's easy for the warrior to find it and to use it to complete your kata without implementing anything.
- Even if not absolutely necessary, it's a good idea to wrap your random tests and the related methods in a function and then call to this function to execute them. This way:
- it's more difficult for a cheater to access to them
- it avoid scopes problem (see below)
- Do NEVER put you internal solution in the preloaded part or objects/structure that contain critical information about it!
Be aware that when the test suite is executed, all the preloaded part, the warrior's code and the test cases are merged together (in this order) before execution. So a global scope exists with several possible troubles:
- Check that you didn't forget the imports needed for the internal solution in the test cases: they are already present in your own solution so your test suite in the edit panel will work even if your forget those in the test cases.
- Do not use too simple names for your variables/methods that are defined in the global scope:
is_prime
as an utility method is the worst choice you could make because it has 90% chances to override the one of the warrior! =>is_prime_34s35fh3s5g42dfhg
is better. Same for simple variables of course (x
=> bad!). Using a wrapper function is especially useful to get rid of this kind of problem. - Last but not least, think about the problems that could appear when a warrior is mutating your input during the random tests (if you pass lists, dictionaries,...). Two ways to avoid problems:
- compute the expected result first, before passing the input to the warrior
- or pass a copy (deepcopy if needed) of the input to the warrior
test.assert_equals(user_func(input), ref_func(input)) => very bad!!
test.assert_equals(user_func(input[:]), ref_func(input)) => OK for list of depth one only (input = [1,2,3])
from copy import deepcopy
test.assert_equals(deepcopy(user_func(input)), ref_func(input)) => OK whatever the input is (almost)
expected = ref_func(input)
test.assert_equals(user_func(input), expected) => OK ! (unless your internal solution mutate the input!)