We can't find the internet
Attempting to reconnect
Something went wrong!
Attempting to reconnect
← Testing with pytest and Hypothesis step 11 of 19
Check a Run-Length Codec with Four Properties
In the last article, Hypothesis generated the inputs and you wrote the properties. The grader cannot run Hypothesis, so here the driver supplies fixed sample strings and you write four property checks. Then you see which of five codecs each check catches.
The format
A run-length codec stores each run of a repeated letter as the letter followed
by its count. Samples contain only the lowercase letters a to z, or are
empty:
"aaab" -> "a3b1"
"aba" -> "a1b1a1"
"" -> ""
- A run is as long as it can be, so
"aaab"has one run of threeas. - Runs stay in their original order.
- A count is a positive decimal number with no leading zeros, and it can have
several digits. Ten
as encode as"a10", not"a9"or two runs. - The codecs work on Python
strvalues.
CODECS maps five names to an (encode, decode) pair: correct,
cap_at_nine, bare_single, off_by_one and case_shifted. Only correct
follows the format. Leave the codecs as they are. Your checks find each bug
through the encode and decode functions they receive.
What to write
Fill in four checks. Each takes a codec's two functions and one sample, and
returns True when its property holds and False otherwise:
def round_trip(encode: Encoder, decode: Decoder, sample: str) -> bool
def oracle(encode: Encoder, decode: Decoder, sample: str) -> bool
def length_preserved(encode: Encoder, decode: Decoder, sample: str) -> bool
def never_crashes(encode: Encoder, decode: Decoder, sample: str) -> bool
Keep all three parameters, even in a check that ignores decode.
| Check | Returns True when |
|---|---|
round_trip |
decoding the encoded sample gives back the sample |
oracle |
the encoder's output equals naive_encode(sample), the reference encoder for the format |
length_preserved |
the counts in the encoder's output, read with counts_in, add up to len(sample) |
never_crashes |
encoding the sample and then decoding the result both finish without raising |
Let exceptions propagate out of your checks. The driver's _holds wrapper
catches any Exception and counts it as a failed check, so a try block in
your check would hide a crash.
What the driver reports
solve(codec=..., samples=...) runs all four checks on every sample. It
returns one key per check, and each key lists the samples that failed that
check. The lists keep the input order and any repeated samples. An empty sample
list gives four empty lists.
For codec="case_shifted" and samples=["", "aaab", "aaab"], solve returns:
{
"round_trip": [],
"oracle": ["aaab", "aaab"],
"length_preserved": [],
"never_crashes": [],
}
This codec writes uppercase letters, as in "A3B1", and its decoder turns them
back into lowercase. So the round trip passes. Only oracle compares the
encoded text with the format, so only oracle fails.
What each check can miss
length_preservedreads only the counts. It passes"A3B1", whose counts are right and whose letters are wrong.never_crashesnever compares the decoded text with the sample.- A check catches a bug only when a sample triggers it.
cap_at_nineencodes every sample correctly if no run is longer than nine. An empty report means these samples passed, and nothing more.
Your code, saved here
Sign in to access your accepted solutions and saved draft history. You can keep reading the lesson without an account.
Sign in to your accountStuck?
Python reference solution
Sign in to track your attempts toward unlocking the reference solution.