2
\$\begingroup\$

I want to test a number of different functions I have written to solve the Fizzbuzz challenge and would like to know what is the best way to check the result?

Each function returns a list of the answers and I want to check the list is correct. One of the functions is shown below

def fizz_buzz_using_boolean():    
    fizz_buzz_list = []

    for x in range(1, 101):            

        fizz = x % 3 == 0 
        buzz = x % 5 == 0
        
        if fizz and buzz:            
            fizz_buzz_list.append('fizzbuzz')
            continue
        elif fizz:            
            fizz_buzz_list.append('fizz')
            continue
        elif buzz:            
            fizz_buzz_list.append('buzz')
            continue
        else:            
            fizz_buzz_list.append(x)            

    return fizz_buzz_list 

My tests look like this:

import pytest
from fizz_buzz import fizz_buzz_if_calc, fizz_buzz_using_boolean


@pytest.fixture
def fizzbuzz_expected_answer():
    """A list of the fizzbuzz answers for 1 - 100"""
    fizz_buzz = [1, 2, 'fizz', 4, 'buzz', 'fizz', 7, 8, 'fizz', 'buzz', 11, 'fizz', 13, 14, 'fizzbuzz', 16, 17, 'fizz', 19, 'buzz', 'fizz', 22, 23, 'fizz', 'buzz', 26, 'fizz', 28, 29, 'fizzbuzz', 31, 32, 'fizz', 34, 'buzz', 'fizz', 37, 38, 'fizz', 'buzz', 41, 'fizz', 43, 44, 'fizzbuzz', 46, 47, 'fizz', 49, 'buzz', 'fizz', 52, 53, 'fizz', 'buzz', 56, 'fizz', 58, 59, 'fizzbuzz', 61, 62, 'fizz', 64, 'buzz', 'fizz', 67, 68, 'fizz', 'buzz', 71, 'fizz', 73, 74, 'fizzbuzz', 76, 77, 'fizz', 79, 'buzz', 'fizz', 82, 83, 'fizz', 'buzz', 86, 'fizz', 88, 89, 'fizzbuzz', 91, 92, 'fizz', 94, 'buzz', 'fizz', 97, 98, 'fizz', 'buzz']
    
    return fizz_buzz


def test_fizz_buzz_using_boolean_has_correct_items(fizzbuzz_expected_answer):
    
    actual = fizz_buzz_using_boolean()

    assert actual == fizzbuzz_expected_answer

I have used a fixture to return the correct answer. Whilst the tests pass I can't find other examples of fixtures being used this way.

The other solutions come to mind is to use a global

import pytest
from fizz_buzz import fizz_buzz_if_calc, fizz_buzz_using_boolean

FIZZBUZZ_EXPECTED_ANSWER = [1, 2, 'fizz', 4, 'buzz', 'fizz', 7, 8, 'fizz', 'buzz', 11, 'fizz', 13, 14, 'fizzbuzz', 16, 17, 'fizz', 19, 'buzz', 'fizz', 22, 23, 'fizz', 'buzz', 26, 'fizz', 28, 29, 'fizzbuzz', 31, 32, 'fizz', 34, 'buzz', 'fizz', 37, 38, 'fizz', 'buzz', 41, 'fizz', 43, 44, 'fizzbuzz', 46, 47, 'fizz', 49, 'buzz', 'fizz', 52, 53, 'fizz', 'buzz', 56, 'fizz', 58, 59, 'fizzbuzz', 61, 62, 'fizz', 64, 'buzz', 'fizz', 67, 68, 'fizz', 'buzz', 71, 'fizz', 73, 74, 'fizzbuzz', 76, 77, 'fizz', 79, 'buzz', 'fizz', 82, 83, 'fizz', 'buzz', 86, 'fizz', 88, 89, 'fizzbuzz', 91, 92, 'fizz', 94, 'buzz', 'fizz', 97, 98, 'fizz', 'buzz']
    

def test_fizz_buzz_using_boolean_has_correct_items():
    
    actual = fizz_buzz_using_boolean()

    assert actual == FIZZBUZZ_EXPECTED_ANSWER

Or my least favourite to use a literal in each test (which will lead to lots of duplicatation)

def test_fizz_buzz_using_boolean_has_correct_items():
    
    actual = fizz_buzz_using_boolean()

    assert actual == [1, 2, 'fizz', 4, 'buzz', 'fizz', 7, 8, 'fizz', 'buzz', 11, 'fizz', 13, 14, 'fizzbuzz', 16, 17, 'fizz', 19, 'buzz', 'fizz', 22, 23, 'fizz', 'buzz', 26, 'fizz', 28, 29, 'fizzbuzz', 31, 32, 'fizz', 34, 'buzz', 'fizz', 37, 38, 'fizz', 'buzz', 41, 'fizz', 43, 44, 'fizzbuzz', 46, 47, 'fizz', 49, 'buzz', 'fizz', 52, 53, 'fizz', 'buzz', 56, 'fizz', 58, 59, 'fizzbuzz', 61, 62, 'fizz', 64, 'buzz', 'fizz', 67, 68, 'fizz', 'buzz', 71, 'fizz', 73, 74, 'fizzbuzz', 76, 77, 'fizz', 79, 'buzz', 'fizz', 82, 83, 'fizz', 'buzz', 86, 'fizz', 88, 89, 'fizzbuzz', 91, 92, 'fizz', 94, 'buzz', 'fizz', 97, 98, 'fizz', 'buzz']

Which method should I use?

\$\endgroup\$
7
  • \$\begingroup\$ When you say "Best" what are you trying to optimize? Performance? Memory usage? You need to be clear to yourself and to the people reviewing the code about what your goal is, otherwise any answers you get will be very opinion based and not necessarily fact based. \$\endgroup\$
    – pacmaninbw
    Jan 23 at 13:22
  • \$\begingroup\$ Apologies I should have used standard rather than best. Resource usage is not a factor in these tests. I am looking to see if there is a standard way of checking the assert. If you were reviewing my code and saw I had used fixtures in this way would you think WTF is going on here? \$\endgroup\$ Jan 23 at 13:28
  • \$\begingroup\$ I'm not a python expert and can't really review the code, it just seemed to me that the question lacked focus. Have you actually implemented this and is it working? That is a requirement for the code review site. \$\endgroup\$
    – pacmaninbw
    Jan 23 at 13:34
  • \$\begingroup\$ Yeah I know. Perhaps read the question and see where I have said.....Whilst the tests pass I can't find other examples of fixtures being used this way. \$\endgroup\$ Jan 23 at 13:35
  • \$\begingroup\$ "Which method should I use?" It's Fizzbuzz. It matters not. Do you want all 3 versions reviewed? Fixtures certainly make sense sometimes, but it's impossible to tell you whether they'll help you in production without seeing the production code. Fizzbuzz is a programming exercise. It helps with practicing new designs, but it's impossible to tell you which to use simply based on the exercise. Please state the goal of the question keeping this in mind. If you're not actually looking for a review, there's not much we can help you with. Please take a look at the help center as well. \$\endgroup\$
    – Mast
    Jan 25 at 8:30
2
\$\begingroup\$

I don't do much python, but I do find your use of a fixture to return the answer a little bizarre. For me, having the actual string in the test would be the way to go. As I understand it, what you don't like about doing this is that you end up with multiple tests, all of which are calling different implementations and then verifying that the implementation returns the same thing. This sounds like something you might want to use a parameterized test for. Rather than passing in the changing data though (since it's the same), you'd parameterize the method under test:

@pytest.mark.parametrize("fizzbuzzer", 
    [fizz_buzz_if_calc, fizz_buzz_using_boolean])
def test_fizz_buzz_has_correct_items(fizzbuzzer):

    actual = fizzbuzzer()

    assert actual == [1, 2, 'fizz', 4, 'buzz', 'fizz', 7, 8, 'fizz', 'buzz', 11, 'fizz', 13, 14, 'fizzbuzz', 16, 17, 'fizz', 19, 'buzz', 'fizz', 22, 23, 'fizz', 'buzz', 26, 'fizz', 28, 29, 'fizzbuzz', 31, 32, 'fizz', 34, 'buzz', 'fizz', 37, 38, 'fizz', 'buzz', 41, 'fizz', 43, 44, 'fizzbuzz', 46, 47, 'fizz', 49, 'buzz', 'fizz', 52, 53, 'fizz', 'buzz', 56, 'fizz', 58, 59, 'fizzbuzz', 61, 62, 'fizz', 64, 'buzz', 'fizz', 67, 68, 'fizz', 'buzz', 71, 'fizz', 73, 74, 'fizzbuzz', 76, 77, 'fizz', 79, 'buzz', 'fizz', 82, 83, 'fizz', 'buzz', 86, 'fizz', 88, 89, 'fizzbuzz', 91, 92, 'fizz', 94, 'buzz', 'fizz', 97, 98, 'fizz', 'buzz']

If the test fails, then you get an indication as to which failed as part of the test name and the follow up information:

________________________________ test_fizz_buzz_has_correct_items[fizz_buzz_if_calc] _________________________________

fizzbuzzer = <function fizz_buzz_if_calc at 0x7f2ff2bbab80>
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.