felixinutero felixinutero - 3 months ago 16
Python Question

Python test class stuck on 'Instantiating tests'

My test class produces the required plot, but I have to manually stop execution every time - the console continues to show 'Instantiating tests'; can anyone spot why the execution never halts? Any tips on increasing my code's 'Pythonic-ness' would also be appreciated!

(Python 3.5 running in PyCharm CE 2016.2.1 on Mac OS X 10.11.6)

# A program to test various sorting algorithms. It generates random lists of various sizes,
# sorts them, and then tests that:
# a. the list is in ascending order
# b. the set of elements is the same as the original list
# c. record the time taken

import random
import timeit
from unittest import TestCase

import matplotlib.pyplot as plt

from Sorter import insertionsort, mergesort, quicksort


class TestSort(TestCase):
def test_sorting(self):

times_insertionsort = [] # holds the running times for insertion sort
times_quicksort = [] # holds the running times for quick sort
times_mergesort = [] # holds the running times for merge sort
lengths = [] # holds the array lengths

# determine the number of lists to be created
for i in range(0, 13):

# initialise a new empty list
pre_sort = []

# determine the list's length, then populate the list with 'random' data
for j in range(0, i * 100):
pre_sort.append(random.randint(0, 1000))

# record the length of the list
lengths.append(len(pre_sort))

# record the time taken by quicksort to sort the list
start_time = timeit.default_timer()
post_quicksort = quicksort(pre_sort)
finish_time = timeit.default_timer()
times_quicksort.append((finish_time - start_time) * 1000)

# record the time taken by insertionsort to sort the list
start_time = timeit.default_timer()
post_insertionsort = insertionsort(pre_sort)
finish_time = timeit.default_timer()
times_insertionsort.append((finish_time - start_time) * 1000)

# record the time taken by mergesort to sort the list
start_time = timeit.default_timer()
post_mergesort = mergesort(pre_sort)
finish_time = timeit.default_timer()
times_mergesort.append((finish_time - start_time) * 1000)

# check that:
# a. the list is in ascending order
# b. the set of elements is the same as the original list
for k in range(0, len(pre_sort) - 1):
self.assertTrue(post_insertionsort[k] in pre_sort)
self.assertTrue(post_insertionsort[k] <= post_insertionsort[k + 1])
self.assertTrue(post_mergesort[k] == post_insertionsort[k])
self.assertTrue(post_mergesort[k] == post_quicksort[k])

# plot the results
plt.plot(lengths, times_insertionsort, 'r')
plt.plot(lengths, times_quicksort, 'g')
plt.plot(lengths, times_mergesort, 'b')
plt.xlabel('List size')
plt.ylabel('Execution time (ms)')
plt.show()

Answer

You need to close the window where the plot is shown in order for the script (your test in this case) to continue/complete/finish. From the docs, emphasis mine:

When you want to view your plots on your display, the user interface backend will need to start the GUI mainloop. This is what show() does. It tells matplotlib to raise all of the figure windows created so far and start the mainloop. Because this mainloop is blocking by default (i.e., script execution is paused), you should only call this once per script, at the end. Script execution is resumed after the last window is closed. Therefore, if you are using matplotlib to generate only images and do not want a user interface window, you do not need to call show (see Generate images without having a window appear and What is a backend?).

Or don't use show() for the tests and just generate an image which you can verify against later.

Comments