> For the complete documentation index, see [llms.txt](https://orsenthil.gitbook.io/learn-python-with-tests/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://orsenthil.gitbook.io/learn-python-with-tests/master.md).

# Learn Python With Tests

This book introduces test driven development in Python. We follow a template while introducing the features of Python.

* Write tests first.
* Exercise tests.
* Fix tests.
* Refactor
* And Repeat

## Inspiration

This book is inspired from the work <https://github.com/quii/learn-go-with-tests/> which introduces Go programming using similar pattern. After reading the Go book, I felt that I could dwell into real-world go projects confidently. I wanted a similar book for Python and I decided to write the current one.

## Boiler plate code.

We want to learn Python without much overhead and dependencies. I wanted to make sure that section of the code can be copied to a filename and run with the python interpreter.

If the repetition annoys you, please excuse me, and skip ahead.

```python
# filename: test_hello.py

if __name__ == '__main__':
    pass
```

* `#` is the start of the comment.
* `#filename` indicates the filename for the snippet.
* The `if __name__ == '__main__'` is a special secret that makes sure that python interpreter will execute the

  whatever comes after this line, only when invoked using `python` interpreter. We typically write the name of the

  tests after this to demonstrate it.&#x20;

## Hello, World

This first chapter can be studied with only python interpreter installed on your system. Please install the latest release of Python from <https://www.python.org/downloads/> before we get started.

On my local system, the interpreter that I use is

```
$ ./python 
Python 3.8.1 (default, Jan 10 2020, 06:25:32) 
[GCC 9.2.1 20191008] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>>
```

### Write tests first - 1

```python
# filename: test_hello.py

def test_hello() -> None:
    expected = "Hello, World!"
    actual = get_hello()
    assert actual == expected, "{actual} != {expected}".format(actual=actual, expected=expected)


if __name__ == '__main__':
    test_hello()
```

### Exercise tests - 1

* Run the tests

```
$ python test_hello.py 
Traceback (most recent call last):
  File "test_hello.py", line 11, in <module>
    test_hello()
  File "test_hello.py", line 6, in test_hello
    actual = get_hello()
NameError: name 'get_hello' is not defined
```

The `NameError` indicates we used a term that is not defined. We have not written our `get_hello` function yet , so let us write it.

### Fix tests - 1

Let us write the `get_hello` method.

```python
def get_hello() -> None:
    pass


def test_hello() -> None:
    expected = "Hello, World!"
    actual = get_hello()
    assert actual == expected, "{actual} != {expected}".format(actual=actual, expected=expected)


if __name__ == '__main__':
    test_hello()
```

### Exercise tests - 2

```
$ python test_hello.py 
Traceback (most recent call last):
  File "test_hello.py", line 15, in <module>
    test_hello()
  File "test_hello.py", line 11, in test_hello
    assert actual == expected, "{actual} != {expected}".format(actual=actual, expected=expected)
AssertionError: None != Hello, World!
```

Now, we see a new error, `AssertionError`, which indicates our expected output and actual output were not matching.

### Fix tests - 2

Let us make sure that `get_hello` returns the string "Hello, World"

```python
def get_hello() -> str:
    return "Hello, World!"
```

The full test code will be

```python
# filename: test_hello.py


def get_hello() -> str:
    return "Hello, World!"


def test_hello() -> None:
    expected = "Hello, World!"
    actual = get_hello()
    assert actual == expected, "{actual} != {expected}".format(actual=actual, expected=expected)


if __name__ == '__main__':
    test_hello()
```

Running this will give no output indicating that our test was successful.

```
$ python test_hello.py
```

### Refactor

This was a very simple introduction to writing a test and exercising it. We don't have anything to refactor. Rest of the book will present examples that will explain the need for refactoring the code after it is written.

## Chapters

* [Setup](/learn-python-with-tests/setup.md)


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://orsenthil.gitbook.io/learn-python-with-tests/master.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
