how to make a calculator 10: part 4


preview

These are the tests I have by the end of the chapter

  1import random
  2import streamlit.testing.v1
  3import tests.test_calculator
  4import unittest
  5
  6
  7class TestStreamlitCalculator(unittest.TestCase):
  8
  9    def setUp(self):
 10        self.tester = streamlit.testing.v1.AppTest.from_file(
 11            'src/streamlit_calculator.py'
 12        )
 13        self.tester.run()
 14
 15    def test_streamlit_calculator_title(self):
 16        self.assertEqual(self.tester.title[0].value, 'Calculator')
 17
 18    def test_streamlit_calculator_display(self):
 19        self.assertEqual(
 20            self.tester.main.children[1].type,
 21            'flex_container'
 22        )
 23
 24    def test_streamlit_calculator_columns(self):
 25        self.assertEqual(len(self.tester.columns), 4)
 26        self.assertEqual(
 27            self.tester.columns[0].button('<-').label,
 28            '<-'
 29        )
 30        self.assertEqual(
 31            self.tester.columns[0].button('7').label,
 32            '7'
 33        )
 34        self.assertEqual(
 35            self.tester.columns[0].button('4').label,
 36            '4'
 37        )
 38        self.assertEqual(
 39            self.tester.columns[0].button('1').label,
 40            '1'
 41        )
 42        self.assertEqual(
 43            self.tester.columns[0].button('+/-').label,
 44            '+/-'
 45        )
 46        self.assertEqual(
 47            self.tester.columns[1].button('C').label,
 48            'C'
 49        )
 50        self.assertEqual(
 51            self.tester.columns[1].button('8').label,
 52            '8'
 53        )
 54        self.assertEqual(
 55            self.tester.columns[1].button('5').label,
 56            '5'
 57        )
 58        self.assertEqual(
 59            self.tester.columns[1].button('2').label,
 60            '2'
 61        )
 62        self.assertEqual(
 63            self.tester.columns[1].button('0').label,
 64            '0'
 65        )
 66
 67        self.assertEqual(
 68            self.tester.columns[2].button('AC').label,
 69            'AC'
 70        )
 71        self.assertEqual(
 72            self.tester.columns[2].button('9').label,
 73            '9'
 74        )
 75        self.assertEqual(
 76            self.tester.columns[2].button('6').label,
 77            '6'
 78        )
 79        self.assertEqual(
 80            self.tester.columns[2].button('3').label,
 81            '3'
 82        )
 83        self.assertEqual(
 84            self.tester.columns[2].button('.').label,
 85            '.'
 86        )
 87
 88        self.assertEqual(
 89            self.tester.columns[3].button('/').label,
 90            '/'
 91        )
 92        self.assertEqual(
 93            self.tester.columns[3].button('X').label,
 94            'X'
 95        )
 96        self.assertEqual(
 97            self.tester.columns[3].button('-').label,
 98            r'\-'
 99        )
100        self.assertEqual(
101            self.tester.columns[3].button('+').label,
102            r'\+'
103        )
104        self.assertEqual(
105            self.tester.columns[3].button('=').label,
106            '='
107        )
108
109    def test_streamlit_session_state(self):
110        expectation = '0'
111        for _ in range(0, 10):
112            number = random.choice('0123456789')
113            (
114                self.tester.button(number)
115                .click().run()
116            )
117            if expectation == '0':
118                expectation = number
119            else:
120                expectation += number
121        self.assertEqual(
122            self.tester.session_state['number'],
123            expectation
124        )
125
126    def test_streamlit_calculator_w_decimals(self):
127        for button in ('0.23.5.6.7.8.9'):
128            (
129                self.tester.button(button)
130                .click().run()
131            )
132        self.assertEqual(
133            self.tester.session_state['number'],
134            '.2356789'
135        )
136
137    def test_streamlit_calculator_w_plus_minus(self):
138        number = '963.0258741'
139        for button in number:
140            (
141                self.tester.button(button)
142                .click().run()
143            )
144        self.tester.button('+/-').click().run()
145        self.assertEqual(
146            self.tester.session_state['number'],
147            f'-{number}'
148        )
149
150        self.tester.session_state['number'] = '0'
151        number = '-963.0258741'
152        for button in number:
153            (
154                self.tester.button(button)
155                .click().run()
156            )
157
158        self.tester.button('+/-').click().run()
159        self.assertEqual(
160            self.tester.session_state['number'],
161            number[1:]
162        )
163
164    def test_streamlit_calculator_reset_state(self):
165        numbers = '123456789'
166        number = random.choice(numbers)
167        self.tester.button(number).click().run()
168        self.assertEqual(
169            self.tester.session_state['number'],
170            number
171        )
172        self.tester.button('C').click().run()
173        self.assertEqual(
174            self.tester.session_state['number'],
175            '0'
176        )
177
178        number = random.choice(numbers)
179        self.tester.button(number).click().run()
180        self.assertEqual(
181            self.tester.session_state['number'],
182            number
183        )
184        self.tester.button('AC').click().run()
185        self.assertEqual(
186            self.tester.session_state['number'],
187            '0'
188        )
189
190    @unittest.skip
191    def test_streamlit_calculator_operations(self):
192        # first_number = '1'
193        first_number = tests.test_calculator.a_random_number()
194        first_number = str(first_number)
195        second_number = '2'
196
197        for character in first_number:
198            if character == '-':
199                self.tester.button('+/-').click().run()
200            else:
201                self.tester.button(character).click().run()
202        self.tester.button('+').click().run()
203        self.assertEqual(
204            self.tester.session_state['first_number'],
205            first_number
206        )
207
208        self.tester.button(second_number).click().run()
209        self.tester.button('=').click().run()
210        self.assertEqual(
211            self.tester.session_state['second_number'],
212            second_number
213        )
214
215        self.assertEqual(
216            self.tester.session_state['number'],
217            str(float(first_number) + float(second_number))
218        )
219
220
221# Exceptions seen
222# NameError
223# AttributeError
224# AssertionError
225# SyntaxError
226# KeyError
227# streamlit.errors.StreamlitDuplicateElementKey
228# TypeError

open the project

  • I change directory to the calculator folder

    cd calculator
    
  • I use pytest-watcher to run the tests

    uv run pytest-watcher . --now
    

    the terminal is my friend, and shows

    rootdir: .../pumping_python/calculator
    configfile: pyproject.toml
    collected 16 items
    
    tests/test_calculator.py .....                                [ 31%]
    tests/test_calculator_website.py ...                          [ 50%]
    tests/test_streamlit_calculator.py ........                   [100%]
    
    ======================== 16 passed in X.YZs =========================
    
  • I open another terminal then use uv in the calculator folder

    uv run streamlit run src/streamlit_calculator.py
    

    the terminal is my friend, and shows

    Collecting usage statistics.
    To deactivate, set browser.gatherUsageStats to false.
    
    
      You can now view your Streamlit app in your browser.
    
      Local URL: http://localhost:8501
      Network URL: http://ABC.DEF.GHI.JKL:8501
      External URL: http://MNO.PQR.STU.VWX:8501
    

    I use ctrl/option on the keyboard and click on http://localhost:8501 with the mouse to open the browser and it shows

    Calculator Streamlit Primary Buttons

test_streamlit_calculator_reset

I want the C and AC buttons to change the number the Calculator shows back to 0, they should reset the calculator.


RED: make it fail


  • I hold ctrl/command on the keyboard and click on tests/test_streamlit_calculator.py with the mouse to open it in the editor

  • I add a test to test_streamlit_calculator.py

    114    def test_streamlit_calculator_w_plus_minus(self):
    115        a_number = '963.0258741'
    116        for key in a_number:
    117            self.press_button(key)
    118        self.assertEqual(
    119            self.tester.session_state['number'], a_number
    120        )
    121
    122        self.press_button('+/-')
    123        self.assertEqual(
    124            self.tester.session_state['number'], f'-{a_number}'
    125        )
    126
    127        self.press_button('+/-')
    128        self.assertEqual(
    129            self.tester.session_state['number'], a_number
    130        )
    131
    132    def test_streamlit_calculator_reset(self):
    133        numbers = '123456789'
    134
    135        number = random.choice(numbers)
    136        self.press_button(number)
    137        self.assertEqual(
    138            self.tester.session_state['number'], number
    139        )
    140
    141        self.press_button('C')
    142        self.assertEqual(
    143            self.tester.session_state['number'], '0'
    144        )
    145
    146
    147# Exceptions seen
    

    the terminal is my friend, and shows AssertionError

    AssertionError: 'X' != '0'
    
    • where 'X' is a random number

    • number = random.choice(numbers) picks a random number from '123456789' (the numbers variable)

    • self.press_button(number) presses the random number

    • self.assertEqual(self.tester.session_state['number'], number) checks that the value of the number key in the session state object is the same as the number that was pressed

    • self.press_button('C') presses the C button

    • self.assertEqual(self.tester.session_state['number'], '0') checks that the the number key in the session state object is set back to 0 after the C button is pressed


GREEN: make it pass


  • I add a function to streamlit_calculator.py

     4def show_number(display):
     5    display.write(streamlit.session_state['number'])
     6
     7
     8def reset_number():
     9    streamlit.session_state['number'] = 0
    10
    11
    12def plus_minus():
    
  • I add the on_click and args parameters to the C button in the add_buttons_to_column_2 function

    65def add_buttons_to_column_2(column_2, display):
    66    column_2.button(
    67        label='C', key='C', width='stretch', on_click=on_click,
    68        args=[reset_number, display], type='primary',
    69    )
    70    column_2.button(
    71        label='8', key='8', width='stretch', on_click=on_click,
    72        args=[add_number_to_state, display, '8'],
    73    )
    74    column_2.button(
    75        label='5', key='5', width='stretch', on_click=on_click,
    76        args=[add_number_to_state, display, '5'],
    77    )
    78    column_2.button(
    79        label='2', key='2', width='stretch', on_click=on_click,
    80        args=[add_number_to_state, display, '2'],
    81    )
    82    column_2.button(
    83        label='0', key='0', width='stretch', on_click=on_click,
    84        args=[add_number_to_state, display, '0'],
    85    )
    86
    87
    88def add_buttons_to_column_3(column_3, display):
    

    the terminal shows AssertionError

    AssertionError: 0 != '0'
    

    I forgot that all the values have been strings so far

  • I change 0 to '0' in the reset_number function

    8def reset_number():
    9    streamlit.session_state['number'] = '0'
    

    the test passes


REFACTOR: make it better


  • I refresh the browser, click on number buttons and when I click on C it clears the numbers I type

  • I add an assertion for the AC button in test_streamlit_calculator_reset in test_streamlit_calculator.py

    129    def test_streamlit_calculator_reset(self):
    130        numbers = '123456789'
    131
    132        number = random.choice(numbers)
    133        self.press_button(number)
    134        self.assertEqual(
    135            self.tester.session_state['number'], number
    136        )
    137
    138        self.press_button('C')
    139        self.assertEqual(
    140            self.tester.session_state['number'], '0'
    141        )
    142
    143        number = random.choice(numbers)
    144        self.press_button(number)
    145        self.assertEqual(
    146            self.tester.session_state['number'], number
    147        )
    148
    149        self.press_button('AC')
    150        self.assertEqual(
    151            self.tester.session_state['number'], '0'
    152        )
    153
    154
    155# Exceptions seen
    

    the terminal is my friend, and shows AssertionError

    AssertionError: 'X' != '0'
    
  • I add the on_click and args parameters to the AC button in the add_buttons_to_column_3 function, in streamlit_calculator.py

     88def add_buttons_to_column_3(column_3, display):
     89    column_3.button(
     90        'AC', key='AC', width='stretch', on_click=on_click,
     91        args=[reset, display], type='primary',
     92    )
     93    column_3.button(
     94        '9', key='9', width='stretch', on_click=on_click,
     95        args=[add_number_to_state, display, '9'],
     96    )
     97    column_3.button(
     98        '6', key='6', width='stretch', on_click=on_click,
     99        args=[add_number_to_state, display, '6'],
    100    )
    101    column_3.button(
    102        '3', key='3', width='stretch', on_click=on_click,
    103        args=[add_number_to_state, display, '3'],
    104    )
    105    column_3.button(
    106        '.', key='.', width='stretch', on_click=on_click,
    107        args=[add_decimal, display],
    108    )
    109
    110
    111def add_buttons_to_column_4(column_4):
    

    the test passes

  • I refresh the browser, click on number buttons and when I click on AC it clears the numbers

  • I add a for loop to test_streamlit_calculator_reset in test_streamlit_calculator.py

    132    def test_streamlit_calculator_reset(self):
    133        numbers = '123456789'
    134
    135        for key in ('C', 'AC'):
    136            with self.subTest(key=key):
    137
    138                number = random.choice(numbers)
    139                self.press_button(number)
    140                self.assertEqual(
    141                    self.tester.session_state['number'],
    142                    number
    143                )
    144
    145                self.press_button(key)
    146                self.assertEqual(
    147                    self.tester.session_state['number'],
    148                    'BOOM!!!'
    149                )
    150
    151        number = random.choice(numbers)
    152        self.press_button(number)
    153        self.assertEqual(
    154            self.tester.session_state['number'], number
    155        )
    

    the terminal is my friend, and shows AssertionError

    SUBFAILED(key='C') ... - AssertionError: '0' != 'BOOM!!!'
    SUBFAILED(key='AC') ... - AssertionError: '0' != 'BOOM!!!'
    
  • I change the expectation

    145                self.press_button(key)
    146                self.assertEqual(
    147                    self.tester.session_state['number'],
    148                    '0'
    149                )
    

    the test passes

  • I remove the other statements from test_streamlit_calculator_reset

    132    def test_streamlit_calculator_reset(self):
    133        numbers = '123456789'
    134
    135        for key in ('C', 'AC'):
    136            with self.subTest(key=key):
    137
    138                number = random.choice(numbers)
    139                self.press_button(number)
    140                self.assertEqual(
    141                    self.tester.session_state['number'],
    142                    number
    143                )
    144
    145                self.press_button(key)
    146                self.assertEqual(
    147                    self.tester.session_state['number'],
    148                    '0'
    149                )
    150
    151
    152# Exceptions seen
    

on to the arithmetic operations


test_streamlit_calculator_operations


RED: make it fail


I add a test for a calculation in test_streamlit_calculator.py

145                self.press_button(key)
146                self.assertEqual(
147                    self.tester.session_state['number'],
148                    '0'
149                )
150
151    def test_streamlit_calculator_operations(self):
152        first_number = '1'
153        second_number = '2'
154
155        self.press_button(first_number)
156        self.press_button('+')
157        self.press_button(second_number)
158        self.press_button('=')
159
160        self.assertEqual(
161            self.tester.session_state['number'],
162            float(first_number)+float(second_number)
163        )
164
165
166# Exceptions seen

the terminal is my friend, and shows KeyError

KeyError: '+'

I forgot that I used r'\+' as the key for addition


GREEN: make it pass


  • I change the key in the test

    155        self.press_button(first_number)
    156        self.press_button(r'\+')
    157        self.press_button(second_number)
    158        self.press_button('=')
    

    the terminal is my friend, and shows AssertionError

    FAILED ... - AssertionError: '12' != 3.0
    
  • The calculator is putting the two numbers together since they are strings. I want it to take the numbers separately then add them as numbers not strings. I add an assertion to check the value of the first number after the + button is pressed

    151    def test_streamlit_calculator_operations(self):
    152        first_number = '1'
    153        second_number = '2'
    154
    155        self.press_button(first_number)
    156        self.press_button(r'\+')
    157        self.assertEqual(
    158            self.tester.session_state['first_number'],
    159            first_number
    160        )
    161
    162        self.press_button(second_number)
    163        self.press_button('=')
    164
    165        self.assertEqual(
    166            self.tester.session_state['number'],
    167            float(first_number)+float(second_number)
    168        )
    

    the terminal is my friend, and shows KeyError

    KeyError: 'st.session_state has no key "first_number".
    Did you forget to initialize it?
    More info: https://docs.streamlit.io/develop/concepts/architecture/session-state#initialization'
    
  • I use the setdefault method to add a default value for the first_number key in the main function, in streamlit_calculator.py

    129def main():
    130    streamlit.title('Calculator')
    131    streamlit.session_state.setdefault('number', '0')
    132    streamlit.session_state.setdefault('first_number', '0')
    133    display = streamlit.container(border=True)
    134
    135    column_1, column_2, column_3, operations = streamlit.columns(4)
    136    add_buttons_to_column_1(column_1, display)
    137    add_buttons_to_column_2(column_2, display)
    138    add_buttons_to_column_3(column_3, display)
    139    add_buttons_to_column_4(operations)
    140
    141
    142if __name__ == '__main__':
    

    the terminal is my friend, and shows AssertionError

    AssertionError: '0' != '1'
    
  • I make a function to change the first_number key of the session state object when the + button is pressed

     8def reset_number():
     9    streamlit.session_state['number'] = '0'
    10
    11
    12def first_number():
    13    first_number = streamlit.session_state['number']
    14    streamlit.session_state['first_number'] = first_number
    15    reset_number()
    16
    17
    18def plus_minus():
    
  • I add the on_click and args parameters to the + button in the add_buttons_to_column_4 function

    117def add_buttons_to_column_4(column_4):
    118    column_4.button(
    119        label='/', key='/', width='stretch', type='primary',
    120    )
    121    column_4.button(
    122        label='X', key='X', width='stretch', type='primary',
    123    )
    124    column_4.button(
    125        label=r'\-', key=r'\-', width='stretch', type='primary',
    126    )
    127    column_4.button(
    128        label=r'\+', key=r'\+', width='stretch', type='primary',
    129    )
    130    column_4.button(
    131        label='=', key='=', width='stretch', type='primary',
    132        on_click=on_click, args=[first_number, display],
    133    )
    134
    135
    136def main():
    

    the terminal is my friend, and shows KeyError and TypeError

  • I add display as a positional argument of the add_buttons_to_column_4 function

    117def add_buttons_to_column_4(column_4, display):
    

    the terminal is my friend, and shows KeyError for more sub tests

  • I add display to the call to the add_buttons_to_column_4 function from the main function

    136def main():
    137    streamlit.title('Calculator')
    138    streamlit.session_state.setdefault('number', '0')
    139    streamlit.session_state.setdefault('first_number', '0')
    140    display = streamlit.container(border=True)
    141
    142    column_1, column_2, column_3, operations = streamlit.columns(4)
    143    add_buttons_to_column_1(column_1, display)
    144    add_buttons_to_column_2(column_2, display)
    145    add_buttons_to_column_3(column_3, display)
    146    add_buttons_to_column_4(operations, display)
    147
    148
    149if __name__ == '__main__':
    

    the terminal is my friend, and shows AssertionError

    AssertionError: '2' != 3.0
    

    Okay! The calculator is no longer adding the strings, the error shows only the second number

  • I add an assertion for the second number after the = button is pressed, in test_streamlit_calculator.py

    151    def test_streamlit_calculator_operations(self):
    152        first_number = '1'
    153        second_number = '2'
    154
    155        self.press_button(first_number)
    156        self.press_button(r'\+')
    157        self.assertEqual(
    158            self.tester.session_state['first_number'],
    159            first_number
    160        )
    161
    162        self.press_button(second_number)
    163        self.press_button('=')
    164        self.assertEqual(
    165            self.tester.session_state['second_number'],
    166            second_number
    167        )
    168
    169        self.assertEqual(
    170            self.tester.session_state['number'],
    171            float(first_number)+float(second_number)
    172        )
    

    the terminal is my friend, and shows KeyError

    KeyError: 'st.session_state has no key "second_number".
    Did you forget to initialize it?
    More info: https://docs.streamlit.io/develop/concepts/architecture/session-state#initialization'
    
  • I use the setdefault method to add a default value for the first_number key in the main function, in streamlit_calculator.py

    136def main():
    137    streamlit.title('Calculator')
    138    streamlit.session_state.setdefault('number', '0')
    139    streamlit.session_state.setdefault('first_number', '0')
    140    streamlit.session_state.setdefault('second_number', '0')
    141    display = streamlit.container(border=True)
    142
    143    column_1, column_2, column_3, operations = streamlit.columns(4)
    144    add_buttons_to_column_1(column_1, display)
    145    add_buttons_to_column_2(column_2, display)
    146    add_buttons_to_column_3(column_3, display)
    147    add_buttons_to_column_4(operations, display)
    148
    149
    150if __name__ == '__main__':
    

    the terminal is my friend, and shows AssertionError

    AssertionError: '0' != '2'
    
  • I make a new function for the result of the calculation, in streamlit_calculator.py

    12def first_number():
    13    first_number = streamlit.session_state['number']
    14    streamlit.session_state['first_number'] = first_number
    15    reset_number()
    16
    17
    18def calculate():
    19    second_number = streamlit.session_state['number']
    20    streamlit.session_state['second_number'] = second_number
    21    reset_number()
    22
    23
    24def plus_minus():
    
  • I add the on_click and args parameters to the = button in the add_buttons_to_column_4 function

    121def add_buttons_to_column_4(column_4, display):
    122    column_4.button(
    123        '/', key='/', width='stretch', type='primary',
    124    )
    125    column_4.button(
    126        'X', key='X', width='stretch', type='primary',
    127    )
    128    column_4.button(
    129        r'\-', key=r'\-', width='stretch', type='primary',
    130    )
    131    column_4.button(
    132        r'\+', key=r'\+', width='stretch', on_click=on_click,
    133        args=[first_number, display], type='primary',
    134    )
    135    column_4.button(
    136        '=', key='=', width='stretch', on_click=on_click,
    137        args=[calculate, display], type='primary',
    138    )
    

    the terminal is my friend, and shows AssertionError

    AssertionError: '0' != 3.0
    

    awesome! The number key of the session state object now resets after the + and = buttons are pressed

  • I add a calculation to the calculate function

    18def calculate():
    19    second_number = streamlit.session_state['number']
    20    streamlit.session_state['second_number'] = second_number
    21    streamlit.session_state['number'] = (
    22        streamlit.session_state['first_number']
    23      + streamlit.session_state['second_number']
    24    )
    25
    26
    27def plus_minus():
    

    the terminal is my friend, and shows AssertionError

    AssertionError: '12' != 3.0
    
  • I change the numbers to floats

     4def calculate():
     5    second_number = streamlit.session_state['number']
     6    streamlit.session_state['second_number'] = second_number
     7    streamlit.session_state['number'] = (
     8        float(streamlit.session_state['first_number'])
     9      + float(streamlit.session_state['second_number'])
    10    )
    

    the test passes

  • I refresh the browser and try the same calculation

    Addition Result

    the result is correct and the number looks different from the others I have seen so far


REFACTOR: make it better


  • when I try another number, the browser and the terminal for the application show TypeError

    TypeError: unsupported operand type(s) for +=: 'float' and 'str'
    
  • I want the result to look the same as the other numbers. I change it to a string in the calculate function

    18def calculate():
    19    second_number = streamlit.session_state['number']
    20    streamlit.session_state['second_number'] = second_number
    21    streamlit.session_state['number'] = str(
    22        float(streamlit.session_state['first_number'])
    23      + float(streamlit.session_state['second_number'])
    24    )
    25
    26
    27def plus_minus():
    

    the terminal is my friend, and shows AssertionError

    AssertionError: '3.0' != 3.0
    

    closer

  • I change the expectation of the assertion in test_streamlit_calculator_operations in test_streamlit_calculator.py

    169        self.assertEqual(
    170            self.tester.session_state['number'],
    171            str(float(first_number)+float(second_number))
    172        )
    

    the test passes

  • I refresh the browser and try the calculation again

    Addition with String Result

    I like it, though I do not need the .0 after the 3

  • I add an assertion for subtraction

    151    def test_streamlit_calculator_operations(self):
    152        first_number = '1'
    153        second_number = '2'
    154
    155        self.press_button(first_number)
    156        self.press_button(r'\+')
    157        self.assertEqual(
    158            self.tester.session_state['first_number'],
    159            first_number
    160        )
    161
    162        self.press_button(second_number)
    163        self.press_button('=')
    164        self.assertEqual(
    165            self.tester.session_state['second_number'],
    166            second_number
    167        )
    168
    169        self.assertEqual(
    170            self.tester.session_state['number'],
    171            str(float(first_number)+float(second_number))
    172        )
    173
    174        self.press_button(first_number)
    175        self.press_button(r'\-')
    176        self.press_button(second_number)
    177        self.press_button('=')
    178        self.assertEqual(
    179            self.tester.session_state['number'],
    180            str(float(first_number)-float(second_number))
    181        )
    182
    183
    184# Exceptions seen
    

    the terminal is my friend, and shows AssertionError

    AssertionError: '4.0120000000000005' != '-1.0'
    

    I need a way to handle the operations

  • I add a variable then an assertion for an 'operation' key in the session state object

    151    def test_streamlit_calculator_operations(self):
    152        first_number = '1'
    153        second_number = '2'
    154
    155        operation = r'\+'
    156        self.press_button(first_number)
    157        # self.press_button(r'\+')
    158        self.press_button(operation)
    159        self.assertEqual(
    160            self.tester.session_state['first_number'],
    161            first_number
    162        )
    163        self.assertEqual(
    164            self.tester.session_state['operation'],
    165            operation
    166        )
    167
    168        self.press_button(second_number)
    169        self.press_button('=')
    170        self.assertEqual(
    171            self.tester.session_state['second_number'],
    172            second_number
    173        )
    174
    175        self.assertEqual(
    176            self.tester.session_state['number'],
    177            str(float(first_number)+float(second_number))
    178        )
    179
    180        self.press_button(first_number)
    181        self.press_button(r'\-')
    182        self.press_button(second_number)
    183        self.press_button('=')
    184        self.assertEqual(
    185            self.tester.session_state['number'],
    186            str(float(first_number)-float(second_number))
    187        )
    

    the terminal is my friend, and shows KeyError

    KeyError: 'st.session_state has no key "operation".
    Did you forget to initialize it?
    More info: https://docs.streamlit.io/develop/concepts/architecture/session-state#initialization'
    
  • I use the setdefault method to add a default value for the operation key in the main function, in streamlit_calculator.py

    the terminal is my friend, and shows AssertionError

    AssertionError: '=' != '\\+'
    
  • I change the value of the operationkey in the first_number function

    12def first_number(operation):
    13    first_number = streamlit.session_state['number']
    14    streamlit.session_state['first_number'] = first_number
    15    streamlit.session_state['operation'] = operation
    16    reset_number()
    17
    18
    19def calculate():
    

    the terminal is my friend, and shows AssertionError

    AssertionError: '0' != '1'
    

    I broke the test for the 'first_number' key that was passing before

  • I add the value for operation to the args list for the r'\+' button in the add_buttons_to_column_4 function

    127def add_buttons_to_column_4(column_4, display):
    128    column_4.button(
    129        label='/', key='/', width='stretch', type='primary',
    130    )
    131    column_4.button(
    132        label='X', key='X', width='stretch', type='primary',
    133    )
    134    column_4.button(
    135        label=r'\-', key=r'\-', width='stretch', type='primary',
    136    )
    137    column_4.button(
    138        label=r'\+', key=r'\+', width='stretch', type='primary',
    139        on_click=on_click, args=[first_number, display, r'\+'],
    140    )
    141    column_4.button(
    142        label='=', key='=', width='stretch', type='primary',
    143        on_click=on_click, args=[calculate, display],
    144    )
    145
    146
    147def main():
    

    the terminal is my friend, and shows AssertionError

    AssertionError: '4.0120000000000005' != '-1.0'
    
  • I add an assertion for the operation key after the - button is pressed, in test_streamlit_calculator.py

    151    def test_streamlit_calculator_operations(self):
    152        first_number = '1'
    153        second_number = '2'
    154
    155        operation = r'\+'
    156        self.press_button(first_number)
    157        # self.press_button(r'\+')
    158        self.press_button(operation)
    159        self.assertEqual(
    160            self.tester.session_state['first_number'],
    161            first_number
    162        )
    163        self.assertEqual(
    164            self.tester.session_state['operation'],
    165            operation
    166        )
    167
    168        self.press_button(second_number)
    169        self.press_button('=')
    170        self.assertEqual(
    171            self.tester.session_state['second_number'],
    172            second_number
    173        )
    174
    175        self.assertEqual(
    176            self.tester.session_state['number'],
    177            str(float(first_number)+float(second_number))
    178        )
    179
    180        operation = r'\-'
    181        self.press_button(first_number)
    182        # self.press_button(r'\-')
    183        self.press_button(operation)
    184        self.press_button(second_number)
    185        self.press_button('=')
    186
    187        self.assertEqual(
    188            self.tester.session_state['operation'],
    189            operation
    190        )
    191
    192        self.assertEqual(
    193            self.tester.session_state['number'],
    194            str(float(first_number)-float(second_number))
    195        )
    196
    197
    198# Exceptions seen
    

    the terminal is my friend, and shows AssertionError

    AssertionError: '\\+' != '\\-'
    
  • I add values for the on_click and args parameters for the r'\-' button in the add_buttons_to_column_4 function in streamlit_calculator.py

    127def add_buttons_to_column_4(column_4, display):
    128    column_4.button(
    129        label='/', key='/', width='stretch', type='primary',
    130    )
    131    column_4.button(
    132        label='X', key='X', width='stretch', type='primary',
    133    )
    134    column_4.button(
    135        label=r'\-', key=r'\-', width='stretch', type='primary',
    136        on_click=on_click, args=[first_number, display, r'\-'],
    137    )
    138    column_4.button(
    139        label=r'\+', key=r'\+', width='stretch', type='primary',
    140        on_click=on_click, args=[first_number, display, r'\+'],
    141    )
    142    column_4.button(
    143        label='=', key='=', width='stretch', type='primary',
    144        on_click=on_click, args=[calculate, display],
    145    )
    146
    147
    148def main():
    

    the terminal is my friend, and shows AssertionError

    AssertionError: '5.01' != '-1.0'
    

    alright! Time to add the calculation for subtraction

  • I use the operation in a dictionary in the calculate function in streamlit_calculator.py

    19def calculate():
    20    arithmetic = {
    21        r'\+': 'add',
    22    }
    23
    24    second_number = streamlit.session_state['number']
    25    streamlit.session_state['second_number'] = second_number
    26    streamlit.session_state['number'] = str(
    27        float(streamlit.session_state['first_number'])
    28      + float(streamlit.session_state['second_number'])
    29    )
    30
    31
    32def plus_minus():
    
  • I use the __getattribute__ method to get the add function from the calculator module

    19def calculate():
    20    arithmetic = {
    21        r'\+': 'add',
    22    }
    23
    24    second_number = streamlit.session_state['number']
    25    streamlit.session_state['second_number'] = second_number
    26    # streamlit.session_state['number'] = str(
    27    #     float(streamlit.session_state['first_number'])
    28    #   + float(streamlit.session_state['second_number'])
    29    # )
    30    operation = arithmetic[streamlit.session_state['operation']]
    31    first_number = float(streamlit.session_state['first_number'])
    32    second_number = float(streamlit.session_state['second_number'])
    33    result = calculator.__getattribute__(operation)(
    34        first_number, second_number
    35    )
    36    streamlit.session_state['number'] = str(result)
    37
    38
    39def plus_minus():
    

    the terminal is my friend, and shows AssertionError

    AssertionError: '2' != '3.0'
    

    and NameError

    NameError: name 'calculator' is not defined. Did you mean: 'calculate'?
    
  • I add an import statement for the calculator module

    1import calculator
    2import streamlit
    3
    4
    5def show_number(display):
    

    the terminal is my friend, and shows AssertionError

    AssertionError: '2' != '-1.0'
    

    and KeyError

    KeyError: '\\-'
    
  • I add a key for r'\-' to the arithmetic dictionary in the calculate function

    20def calculate():
    21    arithmetic = {
    22        r'\+': 'add',
    23        r'\-': 'subtract',
    24    }
    25
    26    second_number = streamlit.session_state['number']
    27    streamlit.session_state['second_number'] = second_number
    28    # streamlit.session_state['number'] = str(
    29    #     float(streamlit.session_state['first_number'])
    30    #   + float(streamlit.session_state['second_number'])
    31    # )
    32    operation = arithmetic[streamlit.session_state['operation']]
    33    first_number = float(streamlit.session_state['first_number'])
    34    second_number = float(streamlit.session_state['second_number'])
    35    result = calculator.__getattribute__(operation)(
    36        first_number, second_number
    37    )
    38    streamlit.session_state['number'] = str(result)
    39
    40
    41def plus_minus():
    

    the terminal is my friend, and shows AssertionError

    AssertionError: '1.0099999999999998' != '-1.0'
    

    the calculation is wrong

  • I add an assertion for the value of the first number in the subtraction operation in test_streamlit_calculator_operations in test_streamlit_calculator.py

    151    def test_streamlit_calculator_operations(self):
    152        first_number = '1'
    153        second_number = '2'
    154
    155        operation = r'\+'
    156        self.press_button(first_number)
    157        # self.press_button(r'\+')
    158        self.press_button(operation)
    159        self.assertEqual(
    160            self.tester.session_state['first_number'],
    161            first_number
    162        )
    163        self.assertEqual(
    164            self.tester.session_state['operation'],
    165            operation
    166        )
    167
    168        self.press_button(second_number)
    169        self.press_button('=')
    170        self.assertEqual(
    171            self.tester.session_state['second_number'],
    172            second_number
    173        )
    174
    175        self.assertEqual(
    176            self.tester.session_state['number'],
    177            str(float(first_number)+float(second_number))
    178        )
    179
    180        operation = r'\-'
    181        self.press_button(first_number)
    182        # self.press_button(r'\-')
    183        self.press_button(operation)
    184        self.assertEqual(
    185            self.tester.session_state['first_number'],
    186            first_number
    187        )
    188
    189        self.press_button(second_number)
    190        self.press_button('=')
    191
    192        self.assertEqual(
    193            self.tester.session_state['operation'],
    194            operation
    195        )
    196
    197        self.assertEqual(
    198            self.tester.session_state['number'],
    199            str(float(first_number)-float(second_number))
    200        )
    201
    202
    203# Exceptions seen
    

    the terminal is my friend, and shows AssertionError

    AssertionError: '3.01' != '1'
    

    ah! the calculation is correct, I have to reset the calculator after it shows the result

  • I reset the calculator after the first operation function

    151def test_streamlit_calculator_operations(self):
    152    first_number = '1'
    153    second_number = '2'
    154
    155    operation = r'\+'
    156    self.press_button(first_number)
    157    # self.press_button(r'\+')
    158    self.press_button(operation)
    159    self.assertEqual(
    160        self.tester.session_state['first_number'],
    161        first_number
    162    )
    163    self.assertEqual(
    164        self.tester.session_state['operation'],
    165        operation
    166    )
    167
    168    self.press_button(second_number)
    169    self.press_button('=')
    170    self.assertEqual(
    171        self.tester.session_state['second_number'],
    172        second_number
    173    )
    174
    175    self.assertEqual(
    176        self.tester.session_state['number'],
    177        str(float(first_number)+float(second_number))
    178    )
    179
    180    self.press_button('AC')
    181
    182    operation = r'\-'
    183    self.press_button(first_number)
    184    # self.press_button(r'\-')
    185    self.press_button(operation)
    186    self.assertEqual(
    187        self.tester.session_state['first_number'],
    188        first_number
    189    )
    190
    191    self.press_button(second_number)
    192    self.press_button('=')
    193
    194    self.assertEqual(
    195        self.tester.session_state['operation'],
    196        operation
    197    )
    198
    199    self.assertEqual(
    200        self.tester.session_state['number'],
    201        str(float(first_number)-float(second_number))
    202    )
    

    the test passes. Wow!

  • I remove the commented lines

    151    def test_streamlit_calculator_operations(self):
    152        first_number = '1'
    153        second_number = '2'
    154
    155        operation = r'\+'
    156        self.press_button(first_number)
    157        self.press_button(operation)
    158        self.assertEqual(
    159            self.tester.session_state['first_number'],
    160            first_number
    161        )
    162        self.assertEqual(
    163            self.tester.session_state['operation'],
    164            operation
    165        )
    166
    167        self.press_button(second_number)
    168        self.press_button('=')
    169        self.assertEqual(
    170            self.tester.session_state['second_number'],
    171            second_number
    172        )
    173
    174        self.assertEqual(
    175            self.tester.session_state['number'],
    176            str(float(first_number)+float(second_number))
    177        )
    178
    179        self.press_button('AC')
    180
    181        operation = r'\-'
    182        self.press_button(first_number)
    183        self.press_button(operation)
    184        self.assertEqual(
    185            self.tester.session_state['first_number'],
    186            first_number
    187        )
    188
    189        self.press_button(second_number)
    190        self.press_button('=')
    191
    192        self.assertEqual(
    193            self.tester.session_state['operation'],
    194            operation
    195        )
    196
    197        self.assertEqual(
    198            self.tester.session_state['number'],
    199            str(float(first_number)-float(second_number))
    200        )
    

    this test is long and will get longer when I add the other two operations

  • I make a dictionary for the operations in test_streamlit_calculator_operations

    151def test_streamlit_calculator_operations(self):
    152    arithmetic_operations = {
    153        r'\+': 'add',
    154        r'\-': 'subtract',
    155        'X': 'multiply',
    156        '/': 'divide'
    157    }
    158
    159    first_number = '1'
    160    second_number = '2'
    
  • I use a for loop with the dictionary

    151    def test_streamlit_calculator_operations(self):
    152        arithmetic_operations = {
    153            r'\+': 'add',
    154            r'\-': 'subtract',
    155            'X': 'multiply',
    156            '/': 'divide'
    157        }
    158
    159        first_number = '1'
    160        second_number = '2'
    161
    162        for operation in arithmetic_operations:
    163            with self.subTest(operation=operation):
    164                self.press_button(first_number)
    165                self.press_button(operation)
    166
    167                self.assertEqual(
    168                    self.tester.session_state['first_number'],
    169                    'BOOM!!!'
    170                )
    171
    172        operation = r'\+'
    

    the terminal is my friend, and shows AssertionError

    SUBFAILED(operation='\\+') ... - AssertionError: '1' != 'BOOM!!!'
    SUBFAILED(operation='\\-') ... - AssertionError: '1' != 'BOOM!!!'
    SUBFAILED(operation='X') ... - AssertionError: '1' != 'BOOM!!!'
    SUBFAILED(operation='/') ... - AssertionError: '1' != 'BOOM!!!'
    FAILED ... - AssertionError: '111' != '1'
    
  • I change the expectation

    166                self.assertEqual(
    167                    self.tester.session_state['first_number'],
    168                    first_number
    169                )
    

    the terminal is my friend, and shows AssertionError

    AssertionError: '111' != '1'
    
  • I reset the calculator with the AC button

    167                self.assertEqual(
    168                    self.tester.session_state['first_number'],
    169                    first_number
    170                )
    171
    172                self.press_button('AC')
    

    the test passes

  • I add an assertion for the operation

    151    def test_streamlit_calculator_operations(self):
    152        arithmetic_operations = {
    153            r'\+': 'add',
    154            r'\-': 'subtract',
    155            'X': 'multiply',
    156            '/': 'divide'
    157        }
    158
    159        first_number = '1'
    160        second_number = '2'
    161
    162        for operation in arithmetic_operations:
    163            with self.subTest(operation=operation):
    164                self.press_button(first_number)
    165                self.press_button(operation)
    166
    167                self.assertEqual(
    168                    self.tester.session_state['first_number'],
    169                    first_number
    170                )
    171
    172                self.assertEqual(
    173                    self.tester.session_state['operation'],
    174                    'BOOM!!!'
    175                )
    176
    177                self.press_button('AC')
    178
    179        operation = r'\+'
    

    the terminal is my friend, and shows AssertionError

    SUBFAILED(operation='\\+') ... - AssertionError: '\\+' != 'BOOM!!!'
    SUBFAILED(operation='\\-') ... - AssertionError: '\\-' != 'BOOM!!!'
    SUBFAILED(operation='X') ... - AssertionError: '\\-' != 'BOOM!!!'
    SUBFAILED(operation='/') ... - AssertionError: '\\-' != 'BOOM!!!'
    FAILED ... - AssertionError: '111' != '1'
    
  • I change the expectation

    171                self.assertEqual(
    172                    self.tester.session_state['operation'],
    173                    operation
    174                )
    

    the terminal is my friend, and shows AssertionError

    SUBFAILED(operation='X') ... - AssertionError: '\\-' != 'X'
    SUBFAILED(operation='/') ... - AssertionError: '\\-' != '/'
    FAILED ... - AssertionError: '111' != '1'
    
  • I add values for the on_click and args parameters to the X button in the add_buttons_to_column_4 function in streamlit_calculator.py

    140def add_buttons_to_column_4(column_4, display):
    141    column_4.button(
    142        label='/', key='/', width='stretch', type='primary',
    143    )
    144    column_4.button(
    145        label='X', key='X', width='stretch', type='primary',
    146        on_click=on_click, args=[first_number, display, 'X'],
    147    )
    148    column_4.button(
    149        label=r'\-', key=r'\-', width='stretch', type='primary',
    150        on_click=on_click, args=[first_number, display, r'\-'],
    151    )
    152    column_4.button(
    153        label=r'\+', key=r'\+', width='stretch', type='primary',
    154        on_click=on_click, args=[first_number, display, r'\+'],
    155    )
    156    column_4.button(
    157        label='=', key='=', width='stretch', type='primary',
    158        on_click=on_click, args=[calculate, display],
    159    )
    

    the terminal is my friend, and shows AssertionError

    SUBFAILED(operation='/') ... - AssertionError: 'X' != '/'
    FAILED ... - AssertionError: '11' != '1'
    
  • I add values for the on_click and args parameters to the / button in the add_buttons_to_column_4 function

    def add_buttons_to_column_4(column_4, display):
        column_4.button(
            label='/', key='/', width='stretch', type='primary',
            on_click=on_click, args=[first_number, display, '/'],
        )
        column_4.button(
            label='X', key='X', width='stretch', type='primary',
            on_click=on_click, args=[first_number, display, 'X'],
        )
        column_4.button(
            label=r'\-', key=r'\-', width='stretch', type='primary',
            on_click=on_click, args=[first_number, display, r'\-'],
        )
        column_4.button(
            label=r'\+', key=r'\+', width='stretch', type='primary',
            on_click=on_click, args=[first_number, display, r'\+'],
        )
        column_4.button(
            label='=', key='=', width='stretch', type='primary',
            on_click=on_click, args=[calculate, display],
        )
    
    
    def main():
    

    the test passes

  • I add a button press for the second number and =, then an assertion in test_streamlit_calculator.py

    151    def test_streamlit_calculator_operations(self):
    152        arithmetic_operations = {
    153            r'\+': 'add',
    154            r'\-': 'subtract',
    155            'X': 'multiply',
    156            '/': 'divide'
    157        }
    158
    159        first_number = '1'
    160        second_number = '2'
    161
    162        for operation in arithmetic_operations:
    163            with self.subTest(operation=operation):
    164                self.press_button(first_number)
    165                self.press_button(operation)
    166                self.assertEqual(
    167                    self.tester.session_state['first_number'],
    168                    first_number
    169                )
    170
    171                self.assertEqual(
    172                    self.tester.session_state['operation'],
    173                    operation
    174                )
    175
    176                self.press_button(second_number)
    177                self.press_button('=')
    178
    179                self.assertEqual(
    180                    self.tester.session_state['second_number'],
    181                    'BOOM!!!'
    182                )
    183
    184                self.press_button('AC')
    

    the terminal is my friend, and shows AssertionError

    SUBFAILED(operation='\\+') ... - AssertionError: '2' != 'BOOM!!!'
    SUBFAILED(operation='\\-') ... - AssertionError: '3.01' != '1'
    SUBFAILED(operation='X') ... - AssertionError: '2' != 'BOOM!!!'
    

    and KeyError

    SUBFAILED(operation='/') t... - KeyError: '1'
    FAILED ... - KeyError: '1'
    
  • I change the expectation

    179                self.assertEqual(
    180                    self.tester.session_state['second_number'],
    181                    second_number
    182                )
    

    the terminal still shows AssertionError and KeyError

  • I add X to the arithmetic dictionary in the calculate function in streamlit_calculator.py

    20def calculate():
    21    arithmetic = {
    22        r'\+': 'add',
    23        r'\-': 'subtract',
    24        'X': 'multiply',
    25    }
    

    the terminal is my friend, and shows KeyError

    SUBFAILED(operation='/') ... - KeyError: 'AC'
    FAILED ... - KeyError: '1'
    
  • I add / to the arithmetic dictionary

    20def calculate():
    21    arithmetic = {
    22        r'\+': 'add',
    23        r'\-': 'subtract',
    24        'X': 'multiply',
    25        '/': 'divide',
    26    }
    27
    28    second_number = streamlit.session_state['number']
    29    streamlit.session_state['second_number'] = second_number
    30    # streamlit.session_state['number'] = str(
    31    #     float(streamlit.session_state['first_number'])
    32    #   + float(streamlit.session_state['second_number'])
    33    # )
    34    operation = arithmetic[streamlit.session_state['operation']]
    35    first_number = float(streamlit.session_state['first_number'])
    36    second_number = float(streamlit.session_state['second_number'])
    37    result = calculator.__getattribute__(operation)(
    38        first_number, second_number
    39    )
    40    streamlit.session_state['number'] = str(result)
    41
    42
    43def plus_minus():
    

    the test passes

  • I add an assertion for the calculation in test_streamlit_calculator.py

    151    def test_streamlit_calculator_operations(self):
    152        arithmetic_operations = {
    153            r'\+': 'add',
    154            r'\-': 'subtract',
    155            'X': 'multiply',
    156            '/': 'divide'
    157        }
    158
    159        first_number = '1'
    160        second_number = '2'
    161
    162        for operation in arithmetic_operations:
    163            with self.subTest(operation=operation):
    164                self.press_button(first_number)
    165                self.press_button(operation)
    166                self.assertEqual(
    167                    self.tester.session_state['first_number'],
    168                    first_number
    169                )
    170
    171                self.assertEqual(
    172                    self.tester.session_state['operation'],
    173                    operation
    174                )
    175
    176                self.press_button(second_number)
    177                self.press_button('=')
    178
    179                self.assertEqual(
    180                    self.tester.session_state['second_number'],
    181                    second_number
    182                )
    183
    184                function = arithmetic_operations[operation]
    185                self.assertEqual(
    186                    self.tester.session_state['number'],
    187                    src.calculator.__getattribute__(function)(
    188                        first_number, second_number
    189                    )
    190                )
    191
    192                self.press_button('AC')
    

    the terminal is my friend, and shows Exceptions

  • I add an import statement at the top of test_streamlit_calculator.py

    the terminal is my friend, and shows AssertionError

    SUBFAILED(operation='\\+') ... - AssertionError: '3.0' != 'brmph?! Numbers only. Try again...'
    SUBFAILED(operation='\\-') ... - AssertionError: '3.01' != '1'
    SUBFAILED(operation='X') ... - AssertionError: '2.0' != 'brmph?! Numbers only. Try again...'
    SUBFAILED(operation='/') ... - AssertionError: '2.01' != '1'
    
  • I change first_number and second_number to floats in the calculation in test_streamlit_calculator.py

    185                function = arithmetic_operations[operation]
    186                self.assertEqual(
    187                    self.tester.session_state['number'],
    188                    src.calculator.__getattribute__(function)(
    189                        float(first_number),
    190                        float(second_number)
    191                    )
    192                )
    

    the terminal is my friend, and shows AssertionError

    SUBFAILED(operation='\\+') ... - AssertionError: '3.0' != 3.0
    SUBFAILED(operation='\\-') ... - AssertionError: '3.01' != '1'
    SUBFAILED(operation='X') ... - AssertionError: '2.0' != 2.0
    SUBFAILED(operation='/') ... - AssertionError: '2.01' != '1'
    
  • I change the expectation to a string

                    function = arithmetic_operations[operation]
                    self.assertEqual(
                        self.tester.session_state['number'],
                        str(
                            src.calculator.__getattribute__(function)(
                                float(first_number),
                                float(second_number)
                            )
                        )
                    )
    

    the test passes

  • I remove the other statements from test_streamlit_calculator_operations

    151    def test_streamlit_calculator_operations(self):
    152        arithmetic_operations = {
    153            r'\+': 'add',
    154            r'\-': 'subtract',
    155            'X': 'multiply',
    156            '/': 'divide'
    157        }
    158
    159        first_number = '1'
    160        second_number = '2'
    161
    162        for operation in arithmetic_operations:
    163            with self.subTest(operation=operation):
    164                self.press_button(first_number)
    165                self.press_button(operation)
    166
    167                self.assertEqual(
    168                    self.tester.session_state['first_number'],
    169                    first_number
    170                )
    171
    172                self.assertEqual(
    173                    self.tester.session_state['operation'],
    174                    operation
    175                )
    176
    177                self.press_button(second_number)
    178                self.press_button('=')
    179
    180                self.assertEqual(
    181                    self.tester.session_state['second_number'],
    182                    second_number
    183                )
    184
    185                function = arithmetic_operations[operation]
    186                self.assertEqual(
    187                    self.tester.session_state['number'],
    188                    str(
    189                        src.calculator.__getattribute__(function)(
    190                            float(first_number),
    191                            float(second_number)
    192                        )
    193                    )
    194                )
    195
    196                self.press_button('AC')
    197
    198
    199# Exceptions seen
    
  • I remove the commented lines from the calculate function in streamlit_calculator.py

    20def calculate():
    21    arithmetic = {
    22        r'\+': 'add',
    23        r'\-': 'subtract',
    24        'X': 'multiply',
    25        '/': 'divide',
    26    }
    27
    28    second_number = streamlit.session_state['number']
    29    streamlit.session_state['second_number'] = second_number
    30
    31    operation = arithmetic[streamlit.session_state['operation']]
    32    first_number = float(streamlit.session_state['first_number'])
    33    second_number = float(streamlit.session_state['second_number'])
    34
    35    result = calculator.__getattribute__(operation)(
    36        first_number, second_number
    37    )
    38
    39    streamlit.session_state['number'] = str(result)
    40
    41
    42def plus_minus():
    

All tests are green and when I try calculations, they work… there is a problem - When I press a new number after I get the result, If I do not press C or AC to reset the number, it adds the number to the end of the result instead of replacing it


close the project

  • I close test_streamlit_calculator.py, streamlit_calculator.py in the editor

  • I click in the first terminal, then use q on the keyboard to leave the tests. The terminal goes back to the command line

  • I change directory to the parent of calculator

    cd ..
    

    the terminal is my friend, and shows

    .../pumping_python
    

    I am back in the pumping_python directory

  • I click in the second terminal, then use ctrl+c on the keyboard to close the web server. The terminal goes back to the command line

  • I change directory to the parent of calculator

    cd ..
    

    the terminal is my friend, and shows

    .../pumping_python
    

    I am back in the pumping_python directory


review

I made a website using Streamlit with a

I used while loops and added tests for

code from the chapter

Do you want to see all the CODE I typed in this chapter?


what is next?

You have completed an amazing journey from pure functions to a real web application! Celebrate it

You now know how to:

  • Build a program with Test-Driven Development

  • Turn it into a Flask_ website

  • Turn it into a Streamlit app

Would you like to see how to make a Calculator with a Large Language Model?


rate pumping python

If this has been a 7 star experience for you, please CLICK HERE to leave a 5 star review of pumping python. It helps other people get into the book too