Python Unittest Problem, Project: Arithmetic Calculator

I can’t understand why am i getting two specific errors when i run the unit test.
Here are the two Errors:

  1. FAIL: test_arrangement (test_module.UnitTests) - which i have handled in my code at # Error handling #1
  2. FAIL: test_too_many_digits (test_module.UnitTests) - which i have handled in my code at # Error handling #4

Here is my full code:

def arithmetic_arranger(problems, show_answer=False):

    # Error handling #1 - Returns string if length of problems exceeds 4.
    if len(problems) > 4 :
        return "Error: Too many problems."

    new_problems = []   

    # these 3 lines must be joined with '\n' character to create output string
    # output string = "\n".join(line1_list, line2_list, line3_list)
    # return output string
    line1_list = []
    line2_list = []
    line3_list = []
    answers_list = []

    # Math Operatos Dictionary
    ops = {"+": (lambda x,y: x+y), "-": (lambda x,y: x-y)} 

    # outer loop iterates over problems list
    for query in problems:
        parts = query.split()           # parts = [num1, operation, num2]
        new_problems.append(parts)      # new_problems =  [['32', '+', '698'], ['3801', '-', '2']]
                     

    # Main loop which:
    # Creating output_lines list along with Error handling on the go
    for single_prob in new_problems:

        # Error handling #2 - Returns Error String if operator is not "+" and "-"
        if single_prob[1] not in ops.keys():
            return "Error: Operator must be '+' or '-'."

        # Error handling #3 - Returns Error String if opreand is not digit
        if not str(single_prob[0]).isnumeric() or not str(single_prob[2]).isnumeric():
            return "Error: Numbers must only contain digits."

        # Error handling #4 - Returns Error String if digits within operand exceed 4 characters
        if len(single_prob[0]) > 4 or len(single_prob[0]) > 4:
            return "Error: Numbers cannot be more than four digits."



        # Dynamically Evaluating output character limit to be displayed with space padding
        char_limit = int(len(single_prob[0]))    # character limit to len(num1 string)
        # Setting character limit to len of num2 string if condition is true
        if len(single_prob[0]) <= len(single_prob[2]):
            char_limit = int(len(single_prob[2]))

        ### Creates line1_list
        # pretty_num1 = num1 string with max 5 characters with spaces on left
        pretty_num1 = str(single_prob[0]).rjust(char_limit+2)       # values = '   32' or ' 3801'
        line1_list.append(pretty_num1)                              # list of num1 elements

        ### Creates line2_list
        # pretty_sec_elemem = str(math operation sign and num2 with max 4 characters with spaces on left)
        pretty_sec_elemem = str(single_prob[1])+str(single_prob[2]).rjust(char_limit+1)     # values = '+ 698' or '-   2' or '+  43'
        line2_list.append(pretty_sec_elemem)


        ### Creates answers_list
        # single_ans = answer of single problem
        if single_prob[1] in ops.keys():
            single_ans = ops[single_prob[1]](int(single_prob[0]),int(single_prob[2]))
        else:
            pass #something about wrong operator

        # pretty_ans =  prettifed answer of individual problem
        pretty_ans = str(single_ans).rjust(char_limit+2)
        answers_list.append(pretty_ans)

        ### Creates line3_list
        line3_list.append('-'*(char_limit+2))       # values = '----' or '-----'


    ### FOR DEBUG PURPOSE ONLY ###
    # prints final lines_list
    # print(line1_list)
    # print(line2_list)
    # print(line3_list)
    # print(answers_list)


    # CONVERTING all lines_lists to lines_string
    line1_string = '    '.join(line1_list)      
    line2_string = '    '.join(line2_list)
    line3_string = '    '.join(line3_list)
    answers_string = '    '.join(answers_list)


    ### FOR DEBUG PURPOSE ONLY ###
    # prints  final output_lines_string
    # print(line1_string)
    # print(line2_string)
    # print(line3_string)
    # print(answers_string)

    # adding output_lines_string into a final_list
    final_list = [line1_string, line2_string, line3_string, answers_string]

    # When True: Removes answers_string from output_string
    if show_answer == False:
        final_list.pop()

    # PRINTING THE FINAL OUTPUT as a STRING with "\n" characters
    output_answer = "\n".join(final_list)

    return output_answer


# print(arithmetic_arranger(["32 + 698", "3801 - 2", "45 + 43", "123 + 49"]))
# print(arithmetic_arranger(
#     ["32 + 8", "1 - 3801", "99995 + 9999", "523 - 49"], True))

# print(arithmetic_arranger(
#     ["44 + 815", "909 - 2", "45 + 43", "123 + 49", "888 + 40", "653 + 87"]))

Here is my full repl console’s full output after run:

   32      3801      45      123
+ 698    -    2    + 43    +  49
-----    ------    ----    -----
F...F.
======================================================================
FAIL: test_arrangement (test_module.UnitTests)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "/home/runner/FrillyPointlessQueryplan/test_module.py", line 14, in test_arrangement
    self.assertEqual(actual, expected, 'Expected different output when calling "arithmetic_arranger()" with ["11 + 4", "3801 - 2999", "1 + 2", "123 + 49", "1 - 9380"]')
AssertionError: 'Error: Too many problems.' != '  11      3801      1      123         1\[79 chars]----'
- Error: Too many problems.
+   11      3801      1      123         1
+  4    - 2999    + 2    +  49    - 9380
----    ------    ---    -----    ------
 : Expected different output when calling "arithmetic_arranger()" with ["11 + 4", "3801 - 2999", "1 + 2", "123 + 49", "1 - 9380"]

======================================================================
FAIL: test_too_many_digits (test_module.UnitTests)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "/home/runner/FrillyPointlessQueryplan/test_module.py", line 29, in test_too_many_digits
    self.assertEqual(actual, expected, 'Expected calling "arithmetic_arranger()" with a problem that has a number over 4 digits long to return "Error: Numbers cannot be more than four digits."')
AssertionError: '     24      3801      45      123\n+ 852[61 chars]----' != 'Error: Numbers cannot be more than four digits.'
+ Error: Numbers cannot be more than four digits.-      24      3801      45      123
- + 85215    -    2    + 43    +  49
- -------    ------    ----    ----- : Expected calling "arithmetic_arranger()" with a problem that has a number over 4 digits long to return "Error: Numbers cannot be more than four digits."

----------------------------------------------------------------------
Ran 6 tests in 0.008s

FAILED (failures=2)

If the run the program alone in sublime or pycharm, it will do its job perfecctly.
But when i run this in the repl.it console with unit test module it always shows the above errors…

Here’s my repl.it link
Can someone please help me??
Also please suggest me if i have commented my code too much?? :sweat_smile:

Thanks for Reading :slight_smile: :slight_smile:

Hi and welcome to the forum!

You have an off-by-one. The maximum number of problems is 5.

I think that perhaps one of these should be [2]

I like your use of printing for debugging. Fun fact, you can also enable/disable a debug mode with:

debug = True
if debug: print("This is debugging info")

so you don’t have to comment/uncomment all the time.

1 Like

THAT IS IT! :heart_eyes:
THANK YOU
It feels like they were dumb mistakes :rofl:
This completes my 1 out of 6 projects for Sci comp using Python.

Do you mind telling what can i do to improve correcting and spotting such errors?

Thank you once Again Jeremy. :yellow_heart:

1 Like

I’m happy to have helped.

Honestly, it takes practice to get good seeing bugs like this. I’ve made similar bugs a lot, which is why I have had practice seeing them!

1 Like

Will practice more.
And thanks again for the Awesome debug = True trick, will definetely use it from now on…

1 Like