# Feedback Report Guide
The feedback report is divided in Testcases. Each Testcase test one ore more functionalities of your submission. Each function is tested by one ore more Testcases. It contains following tags:
* **<span style="color: #3498DB">[TESTCASE]/[NOTE]/[CS]</span>**: Information about Testcase, a Note for the Testcase, [Style Guide](https://hackmd.io/3TEf4WI4QIq8B3BR8YH5uw) Information.
* **<span style="color: #FF2D00">[FAIL]</span>** Something is not correct
* **<span style="color: #E2B007">[TODO]</span>** Something you should check yourself again (Plots, exception messages, Style Guide)
* **<span style="color: #6AB023">[PASS]</span>** All good
<span style="color: #FF2D00">**IMPORTANT:** The testreport does not replace your own testing! </span>
# Correct Submissions (**<span style="color: #6AB023">[PASS]</span>** in test report)
If you hand in a perfectly working submission one Testcase result may look like the following:

**Code:**
```python=3.9
def function_name(argument:int, kword_argument:str=None):
print(f"This Function Prints the value kword_argument: {kword_argument}")
return argument
```
Each Testcase is build up the same way and contains at least following tags:
1) **<span style="color: #3498DB"> [TESTCASE] </span>** This line shows the function call for the Testcase and the Testcase number. This is given as:
`<testcase_number> <return_name> = <file>.<function_name>(<parameters>)`
In the example above:
`00 _ = ass1.function_name(1337, kword_argument='Some Tesxt')`,
where the Testcase number is 0, the function name is `function_name` in the file `ass1`. The function is called with `1337` as first argument and `Some Text` as the keyword argument. The return value is given as `_`.
2) **<span style="color: #3498DB"> [Note] </span>** This note can contain some information about the Testcase which is important to understand the results correctly. This is optional and may not be present for every Testcase
3) **[TIME]** This shows the time in seconds the function took to execute. It also shows the maximum time the function is allowed to execute, in this case 1s.
4) **<span style="color: #6AB023"> [PASS] correct posarg argument </span>** This shows if the positional argument is still correct after the function is called. (inplace modification of positional argument)
5) **<span style="color: #6AB023"> [PASS] kwarg kword_argument </span>** This shows if the keyword argument is still correct after the function is called. (inplace modification of keyword argument)
6) **<span style="color: #6AB023"> [PASS] correct output </span>** This shows if the console output (`print`) is correct.
7) **<span style="color: #6AB023"> [PASS] correct return </span>** This shows if the returned value is correct.
8) **<span style="color: #6AB023"> [PASS] all files OK </span>** This shows if the written files (if files are written) are correct.
# Incorrect Submissions (**<span style="color: #FF2D00">[FAIL]</span>** in test report)
## **<span style="color: #FF2D00">[FAIL] AttributeError: module 'some_module'</span>:**
When your code contains an SyntaxError/Indentation Error (only in `.ipynb` files) or you did not implement the function or your function name is inncorect, you get an AttributeError that the module is not found. To check if you function has an SyntaxError check the CS section of your report here the SyntaxError is stated (further information [here](https://hackmd.io/Mn7AMUNWQXKv3pZDIynBzg?view#Style-Guide-Violations-FAIL-in-CS-)). If you function name is incorrect you have to check it yourself. Make sure you name the functions as stated in the Assignment.

## **<span style="color: #FF2D00">[FAIL] incorrect posarg some_data</span>:**
When your code modifies the positional argument in place when it's not asked to do, the test result looks like following:

Here, a list with the numbers form 10 to 1 are given as argument. The list should be sorted and returned, **without modifying the positional argument**. The test result above shows that the positional argument `some_data` is modified.
Generally, the result is constructed as follows:
`<V/T> <variable_name>: <your result> != <reference result>`.
`V` stands for value (the value is incorrect) and `T` stands for type (the type is incorrect). `<variable_name>` gives the variable (and optional on which position) where the error occures. In the example above this looks like the following:
**V some_data[0]: 1 != 10** shows that the first value in some_data is 1 but should be 10.
**V some_data[0]: 2 != 9** shows that the first value in some_data is 2 but should be 9, and so on...
Here, the first value (left hand of the not equal sign) is always the value *your* code generated and the second value (right side of the not equal sign) is the one produced by the reference solution.
This test result is generated by following code:
**Submission**:
```python=3.9
def mod_posarg(some_data:list):
return some_data.sort()
```
**Reference:**
```python=3.9
def mod_posarg(some_data:list):
return sorted(some_data)
```
*For more information why `sort` and `sorted` are different look [here](https://www.geeksforgeeks.org/python-difference-between-sorted-and-sort/)*
## **<span style="color: #FF2D00">[FAIL] incorrect kwarg some_data</span>:**
When your code modifies the keyword argument when it's not asked to do, the test result looks like following:

Here a list with the numbers form 10 to 1 are given as keyword argument. The list should be sorted and returned, **without modifying the keyword argument**. The test result above shows that the keyword argument `some_data` is modified.
Generally the result is constructed as follows:
`<V/T> <variable_name>: <your result> != <reference result>`.
`V` stands for value (the value is incorrect) and `T` stands for type (the type is incorrect). `<variable_name>` gives the variable (and optional on which position) where the error occures. In the example above this looks like the following:
**V some_data[0]: 1 != 10** shows that the first value in some_data is 1 but should be 10.
**V some_data[0]: 2 != 9** shows that the first value in some_data is 2 but should be 9.
and so on... Here the first value (left hand of the not equal sign) is always the value *your* code generated and the second value (right side of the not equal sign) is the one produced by the reference solution.
This test result is generated by following code:
**Submission**:
```python=3.9
def incorrect_kwarg(some_data:list=None):
some_data.sort()
return some_data
```
**Reference:**
```python=3.9
def incorrect_kwarg(some_data:list=None):
return sorted(some_data)
```
*For more information why `sort` and `sorted` are different look [here](https://www.geeksforgeeks.org/python-difference-between-sorted-and-sort/)*
If the keyword argument has the incorrect name the Testcase will crash and the test result looks like the following:

## **<span style="color: #FF2D00">[FAIL] incorrect output</span>:**
Output in the Testcase references always to output to the console (`print`). When your code prints something it is not asked to, the test result may look like the following:

Notice the two lines of output the first line with the minus (**-**) in fornt of it, is the wrong output created by you. The line with the plus (**+**) in front of it, is the output your code should have generated. The carets (**^**, for single wrong character) or minuses (**-**, for consecutive wrong characters in line) show where in the output the error occurs. Further informations are also given in the section of [incorrect Return](https://hackmd.io/Mn7AMUNWQXKv3pZDIynBzg?view#FAIL-incorrect-return).
This test result is generated by following code:
**Submission**:
```python=3.9
def print_something():
print("The quick brown dog jumps over the lazy fox")
```
**Reference:**
```python=3.9
def print_something():
print("The quick brown fox jumps over the lazy dog")
```
## **<span style="color: #FF2D00">[FAIL] incorrect return</span>:**
When the return value is not correct, the test result could look like the following:

Generally, the result is constructed as follows:
`<V/T> <variable_name>: <your result> != <reference result>`.
`V` stands for value (the value is incorrect) and `T` stands for type (the type is incorrect). `<variable_name>` gives the variable (and optional on which position) where the error occures.
Again notice the first value (left hand of the not equal sign) is always the value *your* code generated and the second value (right side of the not equal sign) is the one produced by the reference solution. In the example above your code returned `11`, while it should have returned `10`.
This test result is generated by following code:
**Submission**:
```python=3.9
def wrong_return():
return 11
```
**Reference:**
```python=3.9
def wrong_return():
return 10
```
Same as with the output when returning a string you get information where the string is incorrect. It shows also if there is something missing or if there is something to much. If there is something to much by you the place with the extra part is marked by the minus (**-**) under it. This is seen below, there is a extra whitespace after the string.

This test result is generated by following code:
**Submission**:
```python=3.9
def incorrect_string():
return "The Dark Knight " # Notice the extra whitespace at the end.
```
**Reference:**
```python=3.9
def incorrect_string():
return "The Dark Knight" # notice no extra whitespace
```
Similar if ther is something missing the location of the missing part is shown by a plus (**+**). In the example below the exlamation mark (**!**) is missing.

This test result is generated by following code:
**Submission**:
```python=3.9
def incorrect_string():
return "The Dark Knight" # Notice the missing "!" at the end.
```
**Reference:**
```python=3.9
def incorrect_string():
return "The Dark Knight!"
```
Similar results are seen when the type of the return value is not correct. In this example the returned list by your code contains integers but there should be floats (`T` at the beginning of line). Notice the values are the same.

This test result is generated by following code:
**Submission**:
```python=3.9
def wrong_return1():
return [1, 2, 3]
```
**Reference:**
```python=3.9
def wrong_return1():
return [1.0, 2.0, 3.0]
```
If the value and the type are incorrect (`T` and `V` at the beginning of line) the test result looks like the following:

This test result is generated by following code:
**Submission**:
```python=3.9
def wrong_return1():
return [3, 4, 5]
```
**Reference:**
```python=3.9
def wrong_return1():
return [1.0, 2.0, 3.0]
```
Also notice if you get `Can't compare <class 'NoneType'> and ...` it's most likely that you did not return anything of return `None`. For example:
```python=3.9
def incorrect_kwarg(some_data:list=None):
return some_data.sort()
```
This would return `None` since `some_data.sort()` returns None`some_data` in place and returns `None`
## **<span style="color: #FF2D00">[FAIL] incorrect content / unexpected file / UNmodified file</span>:**
When the content of the File is inncorect then you get a test result which looks like the following:

Here again every wrong line in the file is shown. The first line with the minus (**-**) in fornt of it is the wrong line created by *you*. The line with the plus (**+**) in front of it is the line your code should have generated. The carets (**^**, for single wrong character) or minuses (**-**, for consecutive wrong characters in line) show where in the line the error occurs.
This test result is generated by following code:
**Submission**:
```python=3.9
def test_file_creation():
with open("created_file.txt", "w") as file:
for line_index in range(3):
file.write(f"This is incorrect line {line_index}\n")
```
**Reference:**
```python=3.9
def test_file_creation():
with open("created_file.txt", "w") as file:
for line_index in range(3):
file.write(f"This is correct line {line_index}\n")
```
If you try to open or write a file you shouldn't or does not exist, the test result will look like the following:

**<span style="color: #FF2D00">[FAIL] unexpected file</span>** This shows that the file `file_not_exists.txt` does not exist or you created this file with your code.
**<span style="color: #FF2D00">[FAIL] UNmodified file</span>:** This shows that you not modified a file which you should have modified.
This test result is generated by following code:
**Submission**:
```python=3.9
def wrong_file_name():
with open("file_not_exists.txt", "w") as file:
file.write(f"Some Content\n")
```
**Reference:**
```python=3.9
def wrong_file_name():
with open("unmodified_file.txt", "w") as file:
file.write(f"Some Content\n")
```
## **<span style="color: #FF2D00">[FAIL] Other errors</span>:**
You may encounter some Errors containing `[FAIL] Expected to crash with ...` This means that your function should have crashed with a specific error but it did not, for example you did not raise an specific Error which was stated in the Assignment.
When you see following Error: `[FAIL] Comparing return with ...`. Then your return value type could be incorrect or our compare function in the testsystem was flawed, pleas contact a Tutor in this case.
## **<span style="color: #FF2D00">[FAIL] SyntaxError / IndentationError</span>:**
When your code contains a SyntaxError or an IndentationError the test result looks like this:

This only occures if you have an SyntaxError in a `.py` file. If you have SyntaxErrors/IndentationErros in a `.ipynb` file you get another Error look [here](https://hackmd.io/Mn7AMUNWQXKv3pZDIynBzg?view#FAIL-AttributeError-module-%E2%80%98some_module%E2%80%99).
Included is the Traceback which shows where the error occures.
<span style="color: #FF2D00">**IMPORTANT:** If you have such a SyntaxError or an IndentationError in your submission your code will not be tested!</span>
# Style Guide Violations (**<span style="color: #FF2D00">[FAIL]</span>** in **<span style="color: #3498DB"> [CS] </span>**)
When your code is not compliant according to the [Style Guide](https://hackmd.io/@info/info_styleguide), the last part of the testreport will contain some information what is incorrect and where. Notice when using Notebooks, the line numbers are always relative to the whole notebook not the individual cell, For example if you have two cells with 5 lines and an Error occures in line 9 it is the fourht line in the second cell.
For the SyntaxErrors/Indentation errors the lines are always relative to the cell itself. For the example above you would get an SyntaxError in line 4 (since it is in line 4 in the second cell).
<span style="color: #FF2D00">**IMPORTANT:** This does not replace the checking of the style guide by yourself. This may not catch all violations automatically. See this only as a **hint**!</span>
A test report with style guide violations may look like the following:
<img src="https://i.imgur.com/rwmjxMK.png" alt="drawing" style="width:450px;"/>

Following Style Guide violations are tested:
**<span style="color: #3498DB"> [CS] ConversionErrors</span>** shows where the SyntaxErrors occured during conversation from Jupyter Notebooks to Python files. This happens if one of your functions has an SyntaxError or Indentation error.
**<span style="color: #3498DB"> [CS] imports</span>** shows if you imported something which is not allowed to import.
**<span style="color: #3498DB"> [CS] tabs</span>** shows if your submission contains tabs. It shows the lines and file where the tabs are present.
**<span style="color: #3498DB"> [CS] line_lengths</span>** shows if there are too long lines. Also the lines and file are shown.
**<span style="color: #3498DB"> [CS] language</span>** shows if your code contains german language.
**<span style="color: #3498DB"> [CS] undefined_variables</span>** shows if you have some undefined variables in your code. It shows also the line (line:offset_from_linestart).
**<span style="color: #3498DB"> [CS] unused_variables</span>** shows if you have unused variables. It shows also the line (line:offset_from_linestart).
**<span style="color: #3498DB"> [CS] unused_import</span>** shows if you have some unused imports. It shows also the line (line:offset_from_linestart).
**<span style="color: #3498DB"> [CS] bad_indentation</span>** shows if your indentations are not correct. This checks if your indentation is a multiple of 4, you don't have overindentation and that your indentations are not mixed with tabs. It shows also the line (line:offset_from_linestart).
**<span style="color: #3498DB"> [CS] is_comparison</span>** checks if you use `==` instead of `is`, were you should use `is`. It shows also the line (line:offset_from_linestart).
**<span style="color: #3498DB"> [CS] pep8_naming</span>** checks if your naming of the variables is pep8 conform. It shows also the line (line:offset_from_linestart).
**<span style="color: #3498DB"> [CS] unclosed_files</span>** checks if you open files without closing them.
**<span style="color: #3498DB"> [CS] if_else_pass</span>** checks if you have a `pass` in an `if`/`else` statement. Also the lines and file are shown.
**<span style="color: #3498DB"> [CS] iteration_instead_of_in</span>** checks if you use a for loop to check if an element is in a sequence instead of `in`. Also the lines and file are shown.
**<span style="color: #3498DB"> [CS] while_for_range_len</span>** checks if you using a for or while loop with `range` and/or `len` where there is no need, because you can iterate over the sequence directly. Also the lines and file are shown.
**<span style="color: #3498DB"> [CS] silenced_exceptions</span>** checks if you have a `try/except` block and you just `pass` in the `except` block. Also the lines and file are shown.
**<span style="color: #3498DB"> [CS] dict_update_wrong</span>** checks if you wrongly use `dict.update`. Also the lines and file are shown.
This test result for the SyntaxError/Indentation Error was generated by following code (each function was in its own cell):
```python=
def this_is_not_a_working_function():
print("This is not a working function)
return "This is not a working function
def indentation_error():
print("This is an indentation error")
def indentation_error_and_syntax_error():
print("This is an indentation error)
```
The rest was generated with the following code:
```python=
import os
import numpy as np
def unclosed_files():
file_= open("test.txt")
file_.read()
def language():
print("Das ist deutscher Text!") # Das ist ein duetscher Kommentar!
def line_lengths():
print("This is a tool long line also comments count") # A very very long line. You can break the line with \ and continue in the next line.
def undefined_variables():
print(new)
print(anotherone)
Hello = 10
Test = 12
def bad_indentation():
print(10)
def if_else_pass(condition):
if condition:
print("Condition is True")
else:
pass
def is_comparison(condition):
if condition == True:
print("Use is here")
if condition == None:
print("Use is here")
def dict_update():
dict_ = {}
dict_.update({"new" : 10})
def silenced_exceptions():
try:
int(10)
except ValueError:
pass
def while_for_range_len(data):
for i in range(len(data)):
print(data[i])
def iteration_instead_of_in(data):
for element in data:
if element == 10:
print("10 is in data")
```