0

Question: How can I return the expected length of a tuple when its constituent element is a list object?

I wrote a very basic unit testing class in Python to begin learning TDD. I want to allow my class to dynamically assign the test case inputs (stored as tuples) depending on how many elements that tuple has. However, when I check the length of a tuple whose only element is a list object the length returned is that of the list object - not the tuple.

Expected functionality:

a = (['a', 'b', 'c'])
len(a) # 1 - one element in the tuple

Actual functionality:

a = (['a', 'b', 'c'])
len(a) # 3 - which appears to be returning len(a[0]) 

Now in the case of a tuple which has multiple elements (including list objects) it does return the expected tuple length. So my issue appears to only crop up when the only element in the tuple is a list object.

Here is the simple unit tester class I wrote. Right now I am getting around this issue by using an else clause on line 13. This doesn't seem like the correct way to handle this.

class Unit_Tester:
  def __init__(self, function, tests):
    self.function_to_test = function
    self.test_list = tests

  def unit_test(self, function_to_test, test_input, expected_output):
      try:
          number_of_inputs = len(test_input)
          print(number_of_inputs)
          if number_of_inputs == 1: function_output = function_to_test(test_input)
          elif number_of_inputs == 2: function_output = function_to_test(test_input[0], test_input[1])
          elif number_of_inputs == 3: function_output = function_to_test(test_input[0], test_input[1], test_input[2])
          else: function_output = function_to_test(test_input)
      except Exception as error:
          print("Error occurred with test input: [{0}] value: {1}\nError Message: {2}\nCorrect the error and try again.\n"
          .format(type(test_input), test_input, error))
      else:
        try:
            assert function_output == expected_output
            print(self.unit_test_response(True, test_input, function_output, expected_output))
        except AssertionError:
            print(self.unit_test_response(False, test_input, function_output, expected_output))

  def unit_test_response(self, correct, test_input, function_output, expected_output): 
      score = "Test Passed" if correct else "Test Failed" 
      return "{0}\nInput: {1}\nExpected Output: {2}\nFunction Output: {3}\n".format(score, test_input, expected_output, function_output)

  def run_unit_tests(self, function_to_test, test_list):  
      for test_tuple in test_list:
          test_input, expected_output = test_tuple
          self.unit_test(function_to_test, test_input, expected_output)

  def run(self):
    self.run_unit_tests(self.function_to_test, self.test_list)
vampiire
  • 1,111
  • 2
  • 15
  • 27
  • `(['a', 'b', 'c'])` isn't a tuple, it's just a list expression with parentheses around it. A one-element tuple needs a comma: `(['a', 'b', 'c'],)` – trent Oct 30 '17 at 21:18
  • ah brilliant thank you. I am new to Python. looking at this problem now that I've stated it I'm wondering if I would be better accepting a list instead. expecting a user (or myself lol) to remember to add that trailing comma seems like an easy oversight – vampiire Oct 30 '17 at 21:19
  • It's kind of unusual to have a tuple whose length you don't know in advance. A list might be better. You might consider posting over on Code Review SE if you have working code and want to know how to make it better. – trent Oct 30 '17 at 21:24
  • ill do that - thanks. originally i was using a spread operator to distribute the inputs (for a multi-parameter test function) but this obviously failed when encountering a list input (because it spread the list) – vampiire Oct 30 '17 at 21:26
  • If you do go to Code Review, note that they have [different topicality guidelines](https://codereview.stackexchange.com/help/on-topic) and rules than Stack Overflow, and the [How to Ask](https://codereview.stackexchange.com/help/how-to-ask) page is also different. – trent Oct 30 '17 at 21:32

0 Answers0