datacamp / pythonwhat

Verify Python code submissions and auto-generate meaningful feedback messages.
http://pythonwhat.readthedocs.io/
GNU Affero General Public License v3.0
69 stars 31 forks source link

Complicated SCT challenge: BLOCK BETA TEST 09/23 #88

Closed hugobowne closed 8 years ago

hugobowne commented 8 years ago

Hi! I have done my best to write an SCT for a solution script in which i have an if-else statement in a for loop in a try-except in a function definition. I apologize that this is ridiculous (it's way easier to test if the solution code actually raises an error! I also have this as an exercise). Below is 1) PEC, 2) solution code , 3) my attempt at SCT.

*\ =pre_exercise_code

fn = 'https://s3.amazonaws.com/assets.datacamp.com/production/course_1342/datasets/tweets.csv'
from urllib.request import urlretrieve
urlretrieve(fn, 'tweets.csv')

# Import pandas
import pandas as pd

# Import Twitter data as dataframe: dataframe
tweets_df = pd.read_csv('tweets.csv')
#Yes, this PEC is overkill (not need to save locally)

*\ =solution

# Define count_entries()
def count_entries(df, col_name='lang'):
    """Return a dictionary with counts of
    occurrences as value for each key."""

    # Initialize an empty dictionary: cols_count
    cols_count = {}

    # Add try block
    try: 
        #...
        col = df[col_name]

        # Iterate over the column in dataframe
        for entry in col:

            # If entry is in cols_count, add 1
            if entry in cols_count.keys():
                cols_count[entry] += 1
            # Else add the entry to cols_count, set the value to 1
            else:
                cols_count[entry] = 1

        # Return the cols_count dictionary
        return cols_count

    # Add except block
    except:
        print('The dataframe does not have a ' + col_name + ' column.')

# Call count_entries(): result1
result1 = count_entries(tweets_df, 'lang')

# Print result1
print(result1)

# Call count_entries(): result2
#result2 = count_entries(tweets_df, 'lang1')

*\ =sct

# All functions used here are defined in the pythonwhat Python package.
# Documentation can also be found at github.com/datacamp/pythonwhat/wiki
def inner_test():
    def inner_inner_test():
        import pandas as pd
        test_df = pd.DataFrame({'a': [0,1], 'lang':[2,2]})
        test_object_after_expression("col", context_vals = [test_df, 'lang'])
        def test_for_iter():
            test_expression_result(extra_env = {'col': pd.Series([2, 2])})

        def test_for_body():
            test_object_after_expression("cols_count",
                                         extra_env = {'cols_count': {"en": 1}},
                                         context_vals = ['et'])
            test_object_after_expression("cols_count",
                                         extra_env = {'cols_count': {"en": 1}},
                                         context_vals = ['en'])

        test_for_loop(
            index=1,
            for_iter=test_for_iter,
            body=test_for_body
        )

        test_object_after_expression("cols_count", context_vals = [test_df, 'lang'])
    #Now test try-except:
    import collections
    handlers = collections.OrderedDict()
    handlers['all'] = lambda: test_function('print')
    test_try_except(index = 1,
                body = inner_inner_test,
                handlers = handlers)

import pandas as pd
test_df = pd.DataFrame({'a': [0,1], 'lang':[2,2]})
test_function_definition(
    "count_entries", body = inner_test,
    results=[[test_df, 'lang']], wrong_result_msg='When defining `count_entries()`, did you return `cols_count`?')

success_msg("Great work!")
filipsch commented 8 years ago

Inside

test_object_after_expression("col", context_vals = [test_df, 'lang'])

which is the third line of inner_inner_test(), you should also specify the value of cols_count:

test_object_after_expression("col", context_vals = [test_df, 'lang'], extra_env = {'cols_count': {}})

Also, make sure to do test_function('print', do_eval = False) inside the handler test, because the value of the printout is not available. You can also use

test_expression_output(extra_env = {'col_name': 'en'})

We are aware that currently, the error messaging is suboptimal; it's saying that something is wrong but not explicitly what is wrong. We already made an issue to address this.

Also, you'd want to specify context_vals and extra_env outside of test_ functions, so that you can also use test_function() etc, and not only the test_expression_*() function. I've made an issue for that too.

hugobowne commented 8 years ago

@filipsch thank you. I have edited the SCT wrt your suggestions and it throws this error now:

screenshot 2016-09-22 10 47 47

I have pasted the new SCT below (I changed line 3 of inner_inner_test() and did test_function('print', do_eval = False)).

It would help if you could post the entire SCT that works, in future, to minimize back-and-forth. Much appreciated, as always.

*\ =sct

# All functions used here are defined in the pythonwhat Python package.
# Documentation can also be found at github.com/datacamp/pythonwhat/wiki
def inner_test():
    def inner_inner_test():
        import pandas as pd
        test_df = pd.DataFrame({'a': [0,1], 'lang':[2,2]})
        test_object_after_expression("col", context_vals = [test_df, 'lang'], extra_env = {'cols_count': {}})
        def test_for_iter():
            test_expression_result(extra_env = {'col': pd.Series([2, 2])})

        def test_for_body():
            test_object_after_expression("cols_count",
                                         extra_env = {'cols_count': {"en": 1}},
                                         context_vals = ['et'])
            test_object_after_expression("cols_count",
                                         extra_env = {'cols_count': {"en": 1}},
                                         context_vals = ['en'])

        test_for_loop(
            index=1,
            for_iter=test_for_iter,
            body=test_for_body
        )

        test_object_after_expression("cols_count", context_vals = [test_df, 'lang'])
    #Now test try-except:
    import collections
    handlers = collections.OrderedDict()
    handlers['all'] = lambda: test_function('print', do_eval=False)
    test_try_except(index = 1,
                body = inner_inner_test,
                handlers = handlers)

import pandas as pd
test_df = pd.DataFrame({'a': [0,1], 'lang':[2,2]})
test_function_definition(
    "count_entries", body = inner_test,
    results=[[test_df, 'lang']], wrong_result_msg='When defining `count_entries()`, did you return `cols_count`?')

success_msg("Great work!")
filipsch commented 8 years ago

I forgot to uncomment the last test_object_after_expression() inside inner_inner_test(). Because it's inside inner_inner_test() so inside the try, you also have to set the cols_count variable through extra_env there:

# Documentation can also be found at github.com/datacamp/pythonwhat/wiki
def inner_test():
    def inner_inner_test():
        import pandas as pd
        test_df = pd.DataFrame({'a': [0,1], 'lang':[2,2]})
        test_object_after_expression("col", context_vals = [test_df, 'lang'], extra_env = {'cols_count': {}})
        def test_for_iter():
            test_expression_result(extra_env = {'col': pd.Series([2, 2])})

        def test_for_body():
            test_object_after_expression("cols_count",
                                         extra_env = {'cols_count': {"en": 1}},
                                         context_vals = ['et'])
            test_object_after_expression("cols_count",
                                         extra_env = {'cols_count': {"en": 1}},
                                         context_vals = ['en'])

        test_for_loop(
            index=1,
            for_iter=test_for_iter,
            body=test_for_body
        )

        test_object_after_expression("cols_count", context_vals = [test_df, 'lang'], extra_env = {'cols_count': {}})
    #Now test try-except:
    import collections
    handlers = collections.OrderedDict()
    handlers['all'] = lambda: test_function('print', do_eval=False)
    test_try_except(index = 1,
                body = inner_inner_test,
                handlers = handlers)

import pandas as pd
test_df = pd.DataFrame({'a': [0,1], 'lang':[2,2]})
test_function_definition(
    "count_entries", body = inner_test,
    results=[[test_df, 'lang']], wrong_result_msg='When defining `count_entries()`, did you return `cols_count`?')
success_msg("Great work!")

You are right that posting the full SCT is easier; I'll do that in the future.

hugobowne commented 8 years ago

this works now. In the near future, I hope to understand this SCT! This course has a higher density of difficult SCTs than most, obv.