test_lambda_function

test_lambda_function(index, arg_names=True, arg_defaults=True, body=None, results=[], errors=[], not_called_msg=None, nb_args_msg=None, arg_names_msg=None, arg_defaults_msg=None, wrong_result_msg=None, no_error_msg=None, expand_message=True, state=None)

Test a lambda function definition.

This function helps you test a lambda function definition. Generally four things can be tested:
  1. The argument names of the function (including if the correct defaults are used)
  2. The body of the functions (does it output correctly, are the correct functions used)
  3. The return value with a certain input
  4. Whether certain inputs generate an error

Custom feedback messages can be set for all these parts, default messages are generated automatically if none are set.

Parameters:
  • index (int) – the number of the lambda function you want to test.
  • arg_names (bool) – if True, the argument names will be tested, if False they won’t be tested. Defaults to True.
  • arg_defaults (bool) – if True, the default values of the arguments will be tested, if False they won’t be tested. Defaults to True.
  • body – this arguments holds the part of the code that will be ran to check the body of the function definition. It should be passed as a lambda expression or a function. The functions that are ran should be other pythonwhat test functions, and they will be tested specifically on only the body of the for loop. Defaults to None.
  • results (list(str)) – a list of strings representing function calls to the lam function. The lam function will be replaced by the actual lambda function from the student and solution code. The result of calling the lambda function will be compared between student and solution.
  • errors (list(str)) – a list of strings representing function calls to the lam function. The lam function will be replaced by the actual lambda function from the student and solution code. It will be checked if an error is generated appropriately for the specified inputs.
  • not_called_msg (str) – message if the function is not defined.
  • nb_args_msg (str) – message if the number of arguments do not matched.
  • arg_names_msg (str) – message if the argument names do not match.
  • arg_defaults_msg (str) – message if the argument default values do not match.
  • wrong_result_msg (str) – message if one of the tested function calls’ result did not match.
  • no_error_msg (str) – message if one of the tested function calls’ result did not generate an error.
  • expand_message (bool) – only relevant if there is a body test. If True, feedback messages defined in the body test will be preceded by ‘In your definition of ___, ‘. If False, test_function_definition() will generate no extra feedback if the body test fails. Defaults to True.
def test_lambda_function(index,
                         arg_names=True,
                         arg_defaults=True,
                         body=None,
                         results=None,
                         errors=None,
                         not_called_msg=None,
                         nb_args_msg=None,
                         arg_names_msg=None,
                         arg_defaults_msg=None,
                         wrong_result_msg=None,
                         no_error_msg=None,
                         expand_message=True)

With test_function_definition(), you can only test user-defined functions that have a name. There is an important class of functions in Python that go by the name of lambda functions. These functions are anonymous, so they don’t necessarily require a name. To be able to test user-coded lambda functions, the test_lambda_function() is available. If you’re familiar with test_function_definition(), you’ll notice some similarities. However, instead of the name, you now have to pass the index; this means you have to specify the lambda function definition to test by number (test the first, second, third ...). Also, because we don’t necessarily have an object represents a lambda function (because it can be anonymous), some tricky things are required to correctly specify the arguments errors and results; the example will give more details.

Example 1

Suppose we want the student to code a lambda function that takes two arguments, word and echo, the latter of which should have default value 1. The lambda function should return the product of word and echo. A solution to this challenge could be the following:

*** =solution
```{python}
echo_word = lambda word, echo = 1: word * echo
```

To test this lambda function definition, you can use the following SCT:

*** =sct
```
test_lambda_function(1,
                 body = lambda: test_student_typed('word'),
                 results = ["lam('test', 2)"],
                 errors = ["lam('a', '2')"])
```

With 1, we tell pythonwhat to test the first lambda function it comes across. Through body, we can specify sub-SCTs to be tested on the body of the lambda function (similar to how test_function_definition does it). With results and errors, you can test the lambda function definition for different input arguments. Notice here that you have to specify a list of function calls as a string. The function you have to call is lam(); behind the scenes, this lam will be replaced by the actual lambda function the student and solution defined. This means that lam('test', 2) will be converted into:

```
(lambda word, echo = 1: word * echo)('test', 2)
```

That way, the system can run the function call, and compare the results between function and solution. Things work the same way for errors.

As usual, the test_lambda_function() will generate a bunch of meaningful automated messages depending on which error the student made (you can override all these messages through the *_msg argument):

submission: <empty>
feedback: "The system wants to check the first lambda function you defined but hasn't found it."

submission: echo_word = lambda wrd: wrd * 1
feedback: "You should define the first lambda function with 2 arguments, instead got 1."

submission: echo_word = lambda wrd, echo: wrd * echo
feedback: "In your definition of the first lambda function, the first argument should be called <code>word</code>, instead got <code>wrd</code>."

submission: echo_word = lambda word, echo = 2: word * echo
feedback: "In your definition of the first lambda function, the second argument should have <code>1</code> as default, instead got <code>2</code>."

submission: echo_word = lambda word, echo = 1: 2 * echo
feedback: "In your definition of the first lambda function, could not find the correct pattern in your code."

submission: echo_word = lambda word, echo = 1: word * echo + 1
feedback: "Calling the the first lambda function with arguments <code>('test', 2)</code> should result in <code>testtest</code>, instead got an error."

submission: echo_word = lambda word, echo = 1: word * echo * 2
feedback = "Calling the first lambda function with arguments <code>('test', 2)</code> should result in <code>testtest</code>, instead got <code>testtesttesttest"

submission: echo_word = lambda word, echo = 1: word * int(echo)
feedback: "Calling the first lambda function with the arguments <code>('a', '2')</code> doesn't result in an error, but it should!"

submission: echo_word = lambda word, echo = 1: word * echo
feedback: "Great job!" (pass)

What about testing usage?

This is practically impossible to do in a robust way; we suggest you do this in an indirect way (checking the output that should be generated, checking the object that should be created, etc).

NOTE: Behind the scenes, pythonwhat has to fetch the value of objects from sub-processes. The required ‘dilling’ and ‘undilling’ can cause issues for exotic objects. For more information on this and possible errors that can occur, read the Processes article.