You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: docs/source/expression_tests.md
+39-4Lines changed: 39 additions & 4 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -281,10 +281,45 @@ For example, the following SCT simply runs `len(x)` in the solution and student
281
281
`call` Syntax
282
282
-------------
283
283
284
-
* almost identical to has_equal_\*.
285
-
* special call syntax
286
-
- string form
287
-
- dict form
284
+
Testing a function definition or lambda may require calling it with some arguments.
285
+
In order to do this, use the `call()` SCT.
286
+
There are two ways to tell it what arguments to pass to the function/lambda,
287
+
288
+
*`call("f (1, 2, x = 3)")` - as a string, where `"f"` gets substituted with the function's name.
289
+
*`call([1,2,3])` - as a list of positional arguments.
290
+
291
+
Below, two alternative ways of specifying the arguments to pass are shown.
292
+
293
+
*** =solution
294
+
```{python}
295
+
def my_fun(x, y = 4, z = ('a', 'b'), *args, **kwargs):
296
+
return [x, y, *z, *args]
297
+
```
298
+
299
+
*** =sct
300
+
```{python}
301
+
Ex().check_function_def('my_fun').call("f(1, 2, (3,4), 5, kw_arg='ok')") # as string
302
+
Ex().check_function_def('my_fun').call([1, 2, (3,4), 5]) # as list
303
+
```
304
+
305
+
```eval_rst
306
+
.. note::
307
+
308
+
Technically, you can get crazy and replace the list approach with a dictionary of the form ``{'args': [POSARG1, POSARG2], 'kwargs': {KWARGS}}``.
309
+
```
310
+
311
+
### Additional Parameters
312
+
313
+
In addition to its first argument, `call()` accepts all the parameters that the expression tests above can (i.e. `has_equal_value`, `has_equal_error`, `has_equal_output`).
314
+
The function call is run at the point where these functions would evaluate an expression.
315
+
Moreover, setting the argument `test` to either "value", "output", or "error" controls which expression test it behaves like.
316
+
317
+
For example, the SCT below shows how to run some `pre_code`, and then evaluate the output of a call.
@@ -29,7 +29,7 @@ For example, in order to test the body of the comprehension above, we could crea
29
29
30
30
***=sct
31
31
```{python}
32
-
(Ex().check_list_comp(1) # focus on first list comp
32
+
(Ex().check_list_comp(0) # focus on first list comp
33
33
.check_body().test_student_typed('i\*2') # focus on its body for test
34
34
)
35
35
```
@@ -52,10 +52,10 @@ This section expands the above example to run tests on each part: body, iter, an
52
52
53
53
***=sct
54
54
```{python}
55
-
list_comp = Ex().check_list_comp(1, missing_msg="Did you include a list comprehension?")
55
+
list_comp = Ex().check_list_comp(0, missing_msg="Did you include a list comprehension?")
56
56
list_comp.check_body().test_student_typed('i\*2')
57
57
list_comp.check_iter().has_equal_value()
58
-
list_comp.check_ifs(1).multi([has_equal_value(context_vals=[i]) for i inrange(0,10)])
58
+
list_comp.check_ifs(0).multi([has_equal_value(context_vals=[i]) for i inrange(0,10)])
59
59
```
60
60
61
61
In this SCT, the first line focuses on the first list comprehension, and assigns it to ``list_comp``, so we can test each part in turn. As a reminder, the code corresponding to each part in the solution code is..
@@ -87,14 +87,14 @@ The line
87
87
88
88
.. code-block:: python
89
89
90
-
list_comp.check_ifs(1).multi([has_equal_value(context_vals=[i] for i inrange(0,10))])
90
+
list_comp.check_ifs(0).multi([has_equal_value(context_vals=[i] for i inrange(0,10))])
91
91
92
92
is a doozy, but can be broken down into
93
93
94
94
.. code-block:: python
95
95
96
96
equal_tests = [has_equal_value(context_vals=[i] for i inrange(0,10))] # collection of has_equal_tests
97
-
list_comp.check_ifs(1).multi(equal_tests) # focus on IFS run equal_tests`
97
+
list_comp.check_ifs(0).multi(equal_tests) # focus on IFS run equal_tests`
98
98
99
99
In this case ``equal_tests`` is a list of ``has_equal_value`` tests that we'll want to perform. ``check_ifs(1)`` grabs the first IFS part, and ``multi(equal_tests)`` runs each ``has_equal_value`` test on that part.
100
100
@@ -133,9 +133,9 @@ in order to test running the inline if expression we could go from list_comp =>
@@ -425,22 +431,138 @@ can be checked with the following SCT
425
431
426
432
.. code:: python
427
433
428
-
(Ex().check_if_else(1) # lines 1-3
429
-
.check_orelse().check_if_else(1) # lines 2-3
434
+
(Ex().check_if_else(0) # lines 1-3
435
+
.check_orelse().check_if_else(0) # lines 2-3
430
436
.check_orelse().has_equal_output() # line 3
431
437
)
432
438
433
439
434
440
function definition / lambda args
435
441
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
436
442
443
+
the ARGS part in function definitions and lambdas may be selected by position or keyword.
444
+
For example, the arguments `a` and `b` below,
445
+
437
446
.. code:: python
438
447
439
-
deff(a, b):
448
+
deff(a, b=2, *some_name):
440
449
BODY
441
450
442
-
*args and **kwargs
451
+
Could be tested using,
452
+
453
+
.. code:: python
454
+
455
+
Ex().check_function_def('f').multi(
456
+
check_args('a').is_default(),
457
+
check_args('b').is_default().has_equal_value(),
458
+
check_args('*args', 'missing a starred argument!')
459
+
)
460
+
461
+
Note that ``check_args('*args')`` and ``check_args('**kwargs')`` may be used to test *args, and **kwargs style parameters, regardless of their name in the function definition.
462
+
463
+
function call args
464
+
~~~~~~~~~~~~~~~~~~~
465
+
466
+
Behind the scenes, ``check_function`` uses the same logic for matching arguments to function signatures as `test_function_v2 <pythonwhat.wiki/test_function_v2.html>`__.
467
+
It also has a ``signature`` argument that accepts a custom signature.
468
+
469
+
Matching Signatures
470
+
^^^^^^^^^^^^^^^^^^^^
471
+
472
+
By default, ``check_function`` tries to match each argument in the function call with the appropriate parameters in that function's call signature.
473
+
For example, all the calls to ``f`` below use ``a = 1`` and ``b = 2``.
474
+
475
+
.. code::
476
+
477
+
def f(a, b): pass
478
+
479
+
f(1, 2) # by position
480
+
f(a = 1, b = 2) # by keyword
481
+
f(1, b = 2) # mixed
482
+
483
+
However, when testing a submission, we may not care how the argument was specified.
Copy file name to clipboardExpand all lines: docs/source/quickstart_guide.md
+9-1Lines changed: 9 additions & 1 deletion
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -55,4 +55,12 @@ the automatic messages for when `x` is undefined or incorrect are replaced with
55
55
56
56
The same holds for `test_output_contains()`: you can use the `no_output_msg` argument to specify a custom message. For more information on all the different arguments you can set in the different `pythonwhat` functions, have a look at the articles in this wiki, describing them in detail.
57
57
58
-
[TODO: quick outline of next steps]
58
+
Next Steps
59
+
----------
60
+
61
+
Test functions in pythonwhat are broken into 4 groups:
62
+
63
+
*[Simple tests](simple_tests/index.rst): look at, e.g., the output produced by an entire code submission.
64
+
*[Part checks](part_checks.rst): focus on specific pieces of code, like a particular for loop.
65
+
*[Expression tests](expression_tests.md): combined with part checks, these run pieces of code and evaluate the outcome.
66
+
*[Logic tests](logic_tests/index.rst): these allow logic like an or statement to be used with SCTs.
An abstract syntax tree (AST) is a way of representing the high-level structure of python code.
10
+
11
+
### Example: quotes
12
+
13
+
Whether you use the concrete syntax `x = "1"` or `x = '1'`, the abstract syntax is the same: x is being assigned to the string "1".
14
+
15
+
### Example: parenthesis
16
+
17
+
Grouping by parentheses produces the same AST, when the same statement would work the same without them.
18
+
For example, `(True or False) and True`, and `True or False and True`, are the same due to operator precedence.
19
+
20
+
### Example: spacing
21
+
22
+
The same holds for different types of spacing that essentially specify the same statement: `x = 1` or `x = 1`.
23
+
24
+
### Caveat: evaluating
25
+
26
+
What the AST doesn't represent is values that are found through evaluation. For example, the first item in the list in
27
+
28
+
```python
29
+
x =1
30
+
[x, 2, 3]
31
+
```
32
+
33
+
and
34
+
35
+
```python
36
+
[1, 2, 3]
37
+
```
38
+
39
+
Is not the same. In the first case, the AST represents that a variable `x` needs to be evaluated in order to find out what its value is. In the second case, it just represents the value `1`.
0 commit comments