<jupyter_start><jupyter_text>Testing ExercisesThe following exercises do not contain solutions. Yet. Instead, we will beasking you to submit your solutions to these exercises and then we will post upsolutions at the start of next week. We encourage you to discuss your approachesor solutions on the course forum!  Exercise 1: MileageThe function 'convert_mileage' converts miles per gallon (US style) toÂ litersper 100 km (metric style):<jupyter_code>gal_to_litre = 3.78541178
mile_to_km = 1.609344
    
def convert_mileage(mpg):
    '''Converts miles per gallon to liters per 100 km'''
    litres_per_100_km = 100 / mpg / mile_to_km * gal_to_litre
    return litres_per_100_km<jupyter_output><empty_output><jupyter_text>Create a subdirectory in your version control directory called `testing-exercises`, thencopy this function into a file in that directory called `mileage.py`. Add morecode to that file to repeatedly ask the user for a mileage in miles per gallon,and output the mileage in liters per 100 km, until the user enters the string`q`. You will need to use the `float()` function to convert from string to afloating point number. Use the '`if __name__ == "__main__":`' trick to ensurethat the module can be imported without executing your testing code.1. Copy `mileage.py` to create `tryexcept.py` Add a try/except block to the newprogram to display a helpful message instead of crashing when users enterinvalid input (such as the number "0" or the name of their favorite hockeyteam). 2. Reading the function again, you realize that accepting 0 or negative valuesmake no sense and should be reported as an error. Look at the exceptions definedin the `exceptions` module (use the built-in `help(...)` or `dir(...)`functions) and decide which of Python's built-in exceptions is most appropriateto use for invalid input. Create a copy of 'tryexcept.py' called 'raiser.py'that raises this exception; modify the main body of your program to catch it;and add a comment inside the file explaining why you chose the exception youdid. (Note: you have to call this file `raiser.py`, not `raise.py` because'import raise' is an error. Â Can you see why?)3. [According to Google](http://www.google.ca/search?q=20+miles+per+gallon+in+litres+per+100+km&gbv=1),20 miles per gallon are equivalent to 11.7607292 liters per 100 km. Use thesevalues to write a unit test. Keep in mind that these floating values are subjectto truncation and rounding errors. Save the test case in a file called`test_mileage.py` and run it using the `nosetests` command. Â Note:`test_mileage.py` should use '`from raiser import convert_mileage`' to get thefinal version of your mileage conversion function.4. Now add a second test case, for 40 miles per gallon equivalent to 5.88036458liters per 100 km and run the tests again. Â Unless you have already fixed theerror that was present in the initial function, your test should fail. Â Findand fix the error; submit your new function in a file called 'final_mileage.py'.   Exercise 2: Testing AveragesThe results of a set of experiments are stored in a file, where the _i-th_ linestores the results of the _i-th_ experiment as a comma-separated list ofintegers. A student is assigned the task of finding the experiment with thesmallest average value. She writes the following code:<jupyter_code>def avg_line(line):
    values = line.split(',')
    count = 0
    total = 0
    for value in values:
        total += int(value)
        count += 1
    return total / count
    
def min_avg(file_name):
    contents = open(file_name)
    averages = []
    for (i, line) in enumerate(contents):
        averages.append((avg_line(line), i))
    contents.close()
    averages.sort()
    min_avg, experiment_number = averages[0]
    return experiment_number<jupyter_output><empty_output><jupyter_text>1. Refactor `min_avg` so that it can be tested without depending on externalfiles. Submit your code in a file called `first_averages.py`.2. Write Nose test cases for both functions. Consider what should happen if thefile is empty. Submit your tests in a file called `test_first_averages.py`.Note: you may assume for now that all input is well formatted, i.e., you do_not_ have to worry about empty lines, lines containing the names of hockeyteams, etc.3. The given specification is ambiguous: what should the result be if two ormore experiments are tied for the minimum average?  Copy 'first_averages.py' tocreate a new file 'second_averages.py'; modify it to handle this case; add acomment to the top explaining what rule you decided to use; and create a file'test_second_averages.py' that tests your changes.4. Another student proposed an alternative implementation of the min_avgfunction:<jupyter_code>def min_avg(file_name):
    contents = open(file_name).readlines()
    min_avg = avg_line(contents[0])
    min_index = 0
    for (i,line) in enumerate(contents):
        current_avg = avg_line(line)
        if current_avg <= min_avg:
            min_avg = current_avg
            min_index = i
    return min_index<jupyter_output><empty_output>
{'fraction_non_alphanumeric': 0.06516587677725119, 'fraction_numerical': 0.0169826224328594, 'mean_word_length': 4.428724544480171, 'pattern_counts': {'":': 1, '<': 14, '<?xml version=': 0, '>': 13, 'https://': 0, 'lorem ipsum': 0, 'www.': 1, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '3', 'dir': 'jupyter-structured-clean-dedup', 'id': '307918', 'license': 'CC-BY-3.0', 'n_tokens_mistral': 1471, 'n_tokens_neox': 1380, 'n_words': 667, 'path': '10-testing-exercises.ipynb', 'repo_name': 'vladov3000/epe_tutorials', 'size': '5064'}