diff --git a/.github/workflows/build_deploy.yml b/.github/workflows/build_deploy.yml new file mode 100644 index 0000000..db6f37c --- /dev/null +++ b/.github/workflows/build_deploy.yml @@ -0,0 +1,43 @@ +# adapted from https://github.com/peaceiris/actions-gh-pages/blob/master/README.md#%EF%B8%8F-static-site-generators-with-nodejs and https://github.com/appleboy/scp-action/blob/master/README.md#example + +name: build and deploy the site + +on: + push: + +jobs: + build-deploy: + runs-on: ubuntu-18.04 + steps: + - name: Checkout repo + uses: actions/checkout@v1 + with: + submodules: true + + - name: Setup Python + uses: actions/setup-python@v1 + with: + python-version: '3.7' + architecture: 'x64' + + - name: Cache dependencies + uses: actions/cache@v1 + with: + path: ~/.cache/pip + key: ${{ runner.os }}-pip-${{ hashFiles('**/requirements.txt') }} + restore-keys: | + ${{ runner.os }}-pip- + + - name: Install dependencies + run: | + python3 -m pip install --upgrade pip + python3 -m pip install -r ./requirements.txt + + - name: Build docs + run: mkdocs build + + - name: Deploy + uses: peaceiris/actions-gh-pages@v3 + with: + github_token: ${{ secrets.GITHUB_TOKEN }} + publish_dir: ./_site diff --git a/.gitignore b/.gitignore index f613f30..b8f798b 100755 --- a/.gitignore +++ b/.gitignore @@ -4,3 +4,5 @@ out.tmp test/.pytest_cache/* __pycache__/* .coverage +htmlcov +_site diff --git a/README.md b/README.md index 5990e18..80b7105 100644 --- a/README.md +++ b/README.md @@ -2,67 +2,6 @@ This tutorial helps you to learn automated testing in Python 3 using the `pytest` framework. -![Moby Dick](images/mobydick.png) +## Credits -## Goal: Count Words in Moby Dick - -*Captain Ahab was vicious because Moby Dick, the white whale, had bitten off his leg. So the captain set sail for a hunt. For months he was searching the sea for the white whale. The captain finally attacked the whale with a harpoon. Unimpressed, the whale devoured captain, crew and ship. The whale won.* - -![tick marks while counting words](../images/counting470.png "Counting words") - -Herman Melville's book *“Moby Dick”* describes the epic fight between the captain of a whaling ship and a whale. In the book, the whale wins by eating most of the other characters. **But does he also win by being mentioned more often?** - -**In this course, you will test a program that is counting words in Melville's book.** - - -## Preparations - -clone the repository: - - :::bash - git clone https://github.com/krother/python_testing_tutorial.git - -install **pytest**: - - :::bash - pip install pytest - -## Chapters - -* [Unit Tests](articles/unit_tests.md) -* [Fixtures](articles/fixtures.md) -* [Parameterized Tests](articles/parameterized.md) -* [Organizing Tests](articles/organizing_tests.md) -* [Test Coverage](articles/test_coverage.md) -* [Recap Puzzle](articles/find_pairs.md) - -## Appendix - -* [Quotes on Testing](articles/quotes.md) -* [Instructions for Trainers](articles/instructions_for_trainers.md) - -## Links - -* [Python Testing Tutorial](https://katyhuff.github.io/python-testing/) - by Kathryn Huff -* [Introduction to pytest](https://www.youtube.com/watch?v=UPanUFVFfzY) - by Michael Tom-Wing and Christie Wilson -* [Test & Code Podcast](http://testandcode.com/) - by Brian Okken -* [The Clean Code Talks – Unit Testing](http://www.youtube.com/watch?v=wEhu57pih5w&feature=channel) -* [Test-Driven-Development](https://www.youtube.com/watch?v=L4hOiGOKSxQ) - by H.Percival - - -## Sources - -Sources for this tutorial: [github.com/krother/python_testing_tutorial](https://github.com/krother/python_testing_tutorial). - -## Copyright - -Feedback and comments are welcome at: [krother@academis.eu](mailto:krother@academis.eu) - -© 2018 Magdalena & Kristian Rother - -Released under the conditions of a Creative Commons -Attribution License 4.0. - -## Contributors - -Kristian Rother, Magdalena Rother, Daniel Szoska +Adopted from [github.com/krother/python_testing_tutorial](https://github.com/krother/python_testing_tutorial). diff --git a/articles/README.md b/articles/README.md new file mode 100644 index 0000000..d96c6cf --- /dev/null +++ b/articles/README.md @@ -0,0 +1,60 @@ +# Python Testing Tutorial + +This tutorial helps you to learn automated testing in Python 3 using the `pytest` framework. + +![Moby Dick](./images/mobydick.png) + +## Goal: Count Words in Moby Dick + +*Captain Ahab was vicious because Moby Dick, the white whale, had bitten off his leg. So the captain set sail for a hunt. For months he was searching the sea for the white whale. The captain finally attacked the whale with a harpoon. Unimpressed, the whale devoured captain, crew and ship. The whale won.* + +![tick marks while counting words](images/counting470.png "Counting words") + +Herman Melville's book *“Moby Dick”* describes the epic fight between the captain of a whaling ship and a whale. In the book, the whale wins by eating most of the other characters. **But does he also win by being mentioned more often?** + +**In this course, you will test a program that is counting words in Melville's book.** + + +## Preparations + +clone the repository: + +```shell +git clone https://github.com/bonartm/python_testing_tutorial.git +``` + +install **pytest**: + +```shell +pip install pytest +``` + +## Getting Started + +Start with the first exercises in the chapter [Unit Tests](unit_tests.md)! + +## Links + +* [Python Testing Tutorial](https://katyhuff.github.io/python-testing/) - by Kathryn Huff +* [Introduction to pytest](https://www.youtube.com/watch?v=UPanUFVFfzY) - by Michael Tom-Wing and Christie Wilson +* [Test & Code Podcast](http://testandcode.com/) - by Brian Okken +* [The Clean Code Talks – Unit Testing](http://www.youtube.com/watch?v=wEhu57pih5w&feature=channel) +* [Test-Driven-Development](https://www.youtube.com/watch?v=L4hOiGOKSxQ) - by H.Percival + + +## Sources + +Sources for this tutorial: [github.com/krother/python_testing_tutorial](https://github.com/krother/python_testing_tutorial). + +## Copyright + +Feedback and comments are welcome at: [krother@academis.eu](mailto:krother@academis.eu) + +© 2018 Magdalena & Kristian Rother + +Released under the conditions of a Creative Commons +Attribution License 4.0. + +## Contributors + +Kristian Rother, Magdalena Rother, Daniel Szoska, Malte Bonart diff --git a/articles/challenges.md b/articles/challenges.md deleted file mode 100644 index 24a0a40..0000000 --- a/articles/challenges.md +++ /dev/null @@ -1,53 +0,0 @@ - -# Challenges - -## 1. Unit Tests - -### 1.1 Test a Python function -The function **main()** in the module **word_counter.py** calculates the number of words in a text body. - -For instance, the following sentence contains **three** words: - - Call me Ishmael - -Your task is to prove that the **main()** function calculates the number of words in the sentence correctly with **three**. - -Use the example test in **test_1_1_unit_test.py**. - -### 1.2 Test proves if code is broken -The test in the module **test_failing_code.py** fails, because there is a bug in the function **word_counter.average_word_length()**. In the sentence - - Call me Ishmael - -The words are **four, two,** and **seven** characters long. This gives an average of: - - >>> (4 + 2 + 7) / 3.0 - 4.333333333333333 - -Your task is to fix the code, so that the test passes. - -Use the example in **test_1_2_broken_code.py**. - -### 1.3 Code proves if tests are broken -The test in the module **test_failing_test.py** fails, because there is a bug in the test file. - -Your task is to fix the test, so that the test passes. Use the example in **test_1_3_broken_test.py**. - - -### 1.4 Test border cases -High quality tests cover many different situations. The most common situations for the program **word_counter.py** include: - -| test case | description | example input | expected output -|-----------|-------------|---------------|----------------- -| empty | input is valid, but empty | "" | 0 -| minimal | smallest reasonable input | "whale" | 1 -| typical | representative input | "whale eats captain" | 3 -| invalid | input is supposed to fail | 777 | *Exception raised* -| maximum | largest reasonable input | *Melville's entire book* | *more than 200000* -| sanity | program recycles its own output | *TextBody A created from another TextBody B* | *A equals B* -| nasty | difficult example | "That #~&%* program still doesn't work!" | 6 - -Your task is to make all tests in **test_1_4_border_cases.py** pass. - - ----- diff --git a/articles/find_pairs.md b/articles/find_pairs.md index 7ccb9ec..9524b71 100644 --- a/articles/find_pairs.md +++ b/articles/find_pairs.md @@ -3,6 +3,6 @@ **Match the test strategies with the correct descriptions.** -![recap puzzle](../images/recap_puzzle.svg) +![recap puzzle](./images/recap_puzzle.svg) This exercise works best on the board or on paper. diff --git a/articles/fixtures.md b/articles/fixtures.md index 8b51b35..cd4441c 100644 --- a/articles/fixtures.md +++ b/articles/fixtures.md @@ -13,12 +13,13 @@ There, add a function that loads the file `data/mobydick_summary.txt`: Place the decorator `@pytest.fixture` on top of it: - :::python3 - import pytest +```python +import pytest - @pytest.fixture - def text_summary(): - return open(...).read() +@pytest.fixture +def text_summary(): + return open(...).read() +``` ---- @@ -26,9 +27,10 @@ Place the decorator `@pytest.fixture` on top of it: Now create a module `test_corpus.py` with a function that uses the fixture: - :::python3 - def test_short_sample(text_summary): - assert count_words(text_summary) == 77 +```python +def test_short_sample(text_summary): + assert count_words(text_summary) == 77 +``` Execute the module with `pytest`. Note that you **do not** need to import `conftest`. Pytest does that automatically. @@ -44,11 +46,12 @@ Create a fixture for the full text of the book `mobydick_full.txt` as well. Create a fixture in `conftest.py` that prepares a dictionary with word counts using the `word_counter.count_words_dict()` function. - :::python3 - from word_counter import count_words_dict +```python +from word_counter import count_words_dict - @pytest.fixture - def count_dict(text_summary): - return ... +@pytest.fixture +def count_dict(text_summary): + return ... +``` Write a simple test that makes sure the dictionary is not empty. diff --git a/images/counting.png b/articles/images/counting.png similarity index 100% rename from images/counting.png rename to articles/images/counting.png diff --git a/images/counting.svg b/articles/images/counting.svg similarity index 100% rename from images/counting.svg rename to articles/images/counting.svg diff --git a/images/counting470.png b/articles/images/counting470.png similarity index 100% rename from images/counting470.png rename to articles/images/counting470.png diff --git a/images/cover.png b/articles/images/cover.png similarity index 100% rename from images/cover.png rename to articles/images/cover.png diff --git a/images/cover.svg b/articles/images/cover.svg similarity index 100% rename from images/cover.svg rename to articles/images/cover.svg diff --git a/images/mobydick.png b/articles/images/mobydick.png similarity index 100% rename from images/mobydick.png rename to articles/images/mobydick.png diff --git a/images/recap_puzzle.svg b/articles/images/recap_puzzle.svg similarity index 100% rename from images/recap_puzzle.svg rename to articles/images/recap_puzzle.svg diff --git a/images/testing_is_incomplete.png b/articles/images/testing_is_incomplete.png similarity index 100% rename from images/testing_is_incomplete.png rename to articles/images/testing_is_incomplete.png diff --git a/images/testing_is_incomplete.svg b/articles/images/testing_is_incomplete.svg similarity index 100% rename from images/testing_is_incomplete.svg rename to articles/images/testing_is_incomplete.svg diff --git a/articles/instructions_for_trainers.md b/articles/instructions_for_trainers.md deleted file mode 100644 index 7ca860c..0000000 --- a/articles/instructions_for_trainers.md +++ /dev/null @@ -1,56 +0,0 @@ -# Instructions for Trainers - -This chapter aims to help you to run a tutorial on automated testing in Python. -Our aim is to save you preparation time while leaving room for your own ideas. -Most of all, we hope you have fun in your next course. - -## How to run a course using this toolkit - -1. Introduce the Moby Dick Theme to your trainees -2. Clone the repository -3. Share the exercises with your trainees -5. Start coding your way through the chapters - -## Lesson plan for a 180' tutorial - -| module | topic | time | -|--------|-------|------| -| warm-up | introduce the Moby Dick theme | 5' | -| warm-up | announce training objectives | 5' | -| | -| **part 1** | **Writing automatic tests in Python** | 45’ | -| warm-up | warmup question | 5' | -| new content | presentation: Unit Tests in pytest | 10’ | -| application | exercises: Unit Tests | 25’ | -| wrap-up | Q & A | 5’ | -| | -| **part 2** | **Test Strategies (45')** | | -| warm-up | quiz on test strategies | 10' | -| new content | presentation on Test-Driven-Development | 10’ | -| application | exercises: fixtures and parameterized tests | 20' | -| wrap-up | Q & A | 5’ | -| | -| **break** | | 10’ | -| | -| **part 3** | **Tests data and test suites (45')** | | -| warm-up | multiple choice questions | 10' | -| new content | presentation on Integration and Acceptance Tests | 10’ | -| application | exercises: test collection and test coverage | 20' | -| wrap-up | Q & A | 5’ | -| | -| **summary** | **Benefits of testing (25')** | | -| transfer | group discussion on benefits of testing | 15’ | -| wrap-up | recap puzzle | 5’ | -| finishing | summary | 4’ | -| finishing | goodbye | 1' | - -I used a similar lesson plan to conduct a training at EuroPython 2014. -The audience consisted of about 60 Python programmers, including beginners and seasoned developers. - -## Why the Moby Dick example? - -Three main reasons: - -* The implementation is simple enough for beginners -* Counting words yields different border cases (because of upper/lower case, special characters etc), making a sufficient use case for testing -* You can easily change the theme to another book from [Project Gutenberg](http://www.gutenberg.org/). diff --git a/articles/mock_objects.md b/articles/mock_objects.md deleted file mode 100644 index 428b9b2..0000000 --- a/articles/mock_objects.md +++ /dev/null @@ -1,8 +0,0 @@ - -# Mock Objects - -### Exercise 1: Using a Mock Object - -The function **word_report.get_top_words()** requires an instance of the class **TextBody**. You need to test the function, excluding the possibility that the **TextBody** class is buggy. To do so, you need to replace the class by a **Mock Object**, a simple placeholder. - -Your task is to write a test for the function **word_counter.get_top_words()** that does not use the class **TextBody**. diff --git a/articles/multiple_packages.md b/articles/multiple_packages.md deleted file mode 100644 index 479ea20..0000000 --- a/articles/multiple_packages.md +++ /dev/null @@ -1,20 +0,0 @@ -### Exercise 5: Import test data in multiple test packages -In a big software project, your tests are distributed to two packages. Both **test_first.py** and **test_second.py** require the variable **MOBYDICK_SUMMARY** from the module **test data.py**. The package structure is like this: - - testss/ - test_a/ - __init__.py - test_first.py - test_b/ - __init__.py - test_second.py - __init__.py - test_data.py - test_all.py - -Your task is to make sure that the variable **MOBYDICK_SUMMARY** is correctly imported to both test modules, so that the tests pass for all of: - - tests/test_a/test_first.py - tests/test_b/test_second.py - tests/test_all.py - diff --git a/articles/organizing_tests.md b/articles/organizing_tests.md index fd79c5b..7f3402b 100644 --- a/articles/organizing_tests.md +++ b/articles/organizing_tests.md @@ -9,11 +9,12 @@ Make sure the name of the class starts with the word `Test`. Indent your test functions so that they belong to the class. Add `self` as the first parameter of each function: - :::python3 - class TestDummy: +```python +class TestDummy: - def test_dummy(self): - assert ... + def test_dummy(self): + assert ... +``` ---- @@ -21,8 +22,9 @@ Add `self` as the first parameter of each function: Run all tests written so far by simply typing - :::bash - pytest +```bash +python -m pytest +``` ---- @@ -30,18 +32,21 @@ Run all tests written so far by simply typing Run only one test file: - :::bash - pytest FILE_NAME +```bash +python -m pytest FILE_NAME +``` Run only one test class: - :::bash - pytest FILE_NAME::CLASS_NAME +```bash +pytest -m pytest FILE_NAME::CLASS_NAME +``` Finally, run a single test: - :::bash - pytest FILE_NAME::CLASS_NAME::TEST_NAME +```bash +pytest -m pytest FILE_NAME::CLASS_NAME::TEST_NAME +``` ---- @@ -51,7 +56,8 @@ Find out which options of pytest do the following: *more verbose output | re-run failing tests | stop on first test that fails* - :::bash - pytest -lf - pytest -v - pytest -x +```bash +pytest --lf +pytest -v +pytest -x +``` diff --git a/articles/parameterized.md b/articles/parameterized.md index 72077fd..be5b8fe 100644 --- a/articles/parameterized.md +++ b/articles/parameterized.md @@ -5,7 +5,7 @@ The tests in `test_parameterized.py` check a list of pairs (word, count) that apply to the text file `mobydick_summary.txt`: - :::python3 + ```python PAIRS = [ ('whale', 5), ('goldfish', 0), @@ -14,6 +14,7 @@ The tests in `test_parameterized.py` check a list of pairs (word, count) that ap ('jellyfish', 99), ('harpoon', 1), ] + ``` Run the tests and see what happens. @@ -34,12 +35,13 @@ We will create six tests from the example data. Use the **test parametrization in pytest**. Change the test function by adding the following decorator: - :::python3 - import pytest +```python +import pytest - @pytest.mark.parametrize('word, number', PAIRS) - def test_count_words_dict(word, number): - ... +@pytest.mark.parametrize('word, number', PAIRS) +def test_count_words_dict(word, number): + ... +``` The two arguments will be filled in automatically. Now remove the `for` loop. diff --git a/articles/test_coverage.md b/articles/test_coverage.md index 0fc6f34..a7b16c1 100644 --- a/articles/test_coverage.md +++ b/articles/test_coverage.md @@ -3,8 +3,9 @@ For the next exercises, you need to install a small plugin: - :::bash - pip install pytest-cov +```bash +pip install pytest-cov +``` ---- @@ -12,8 +13,9 @@ For the next exercises, you need to install a small plugin: Calculate the percentage of code covered by automatic tests: - :::bash - pytest --cov=. +```bash +python -m pytest --cov=. +``` Instead of the `.` you can insert the path you would like to see in the coverage report. @@ -24,8 +26,9 @@ Check whether any hidden files have appeared. ### Exercise 2: Identify uncovered lines Find out which lines are not covered by tests. Execute - :::bash - coverage html + ```bash + python -m pytest --cov=. --cov-report term-missing + ``` Open the resulting file `htmlcov/index.html` in a web browser. diff --git a/articles/unit_tests.md b/articles/unit_tests.md index ee87499..96d1050 100644 --- a/articles/unit_tests.md +++ b/articles/unit_tests.md @@ -5,17 +5,19 @@ #### How many words are in the following sentence? - :::bash - Call me Ishmael. +```bash +Call me Ishmael. +``` ---- #### How many words are in the next sentence? - :::bash - "you haint no objections to sharing a harpooneer's blanket, - have ye? I s'pose you are goin' a-whalin', - so you'd better get used to that sort of thing." +```bash +"you haint no objections to sharing a harpooneer's blanket, +have ye? I s'pose you are goin' a-whalin', +so you'd better get used to that sort of thing." +``` ---- @@ -26,15 +28,17 @@ The function `count_words()` in the module **word_counter.py** calculates the nu For instance, we would expect the following input to result in a word count of `3`: - :::bash - Call me Ishmael +```bash +Call me Ishmael +``` Your task is to prove that the `count_words()` function in fact returns `3`. Run the example test in `test_unit_test.py` with - :::bash - pytest test_unit_test.py +```bash +python -m pytest test/test_unit_test.py +``` ---- @@ -55,7 +59,7 @@ Run the test in `test_broken_test.py` and inspect the output. It fails, because there is a bug in the test file. -Fix the test code, so that the test passes. +Fix the *test code*, so that the test passes. ---- diff --git a/mkdocs.yml b/mkdocs.yml new file mode 100644 index 0000000..bffe704 --- /dev/null +++ b/mkdocs.yml @@ -0,0 +1,50 @@ +site_name: Python Testing Tutorial +site_description: This tutorial helps you to learn automated testing in Python 3 using the `pytest` framework. +site_author: Malte Boanrt +copyright: Magdalena & Kristian Rother +site_url: 'https://bonartm.github.io/python_testing_tutorial/' +theme: + name: material + palette: + primary: 'blue grey' + accent: 'light blue' +site_dir: ./_site +docs_dir: ./articles + +plugins: + - search + - git-revision-date-localized + +markdown_extensions: + - footnotes + - admonition + - pymdownx.arithmatex + - pymdownx.betterem: + smart_enable: all + - pymdownx.caret + - pymdownx.critic + - pymdownx.details + - pymdownx.emoji: + emoji_generator: !!python/name:pymdownx.emoji.to_svg + - pymdownx.inlinehilite + - pymdownx.magiclink + - pymdownx.mark + - pymdownx.smartsymbols + - pymdownx.superfences + - pymdownx.tasklist: + custom_checkbox: true + - pymdownx.tilde + - codehilite: + guess_lang: false + - toc: + permalink: true + +nav: + - Unit Tests: 'unit_tests.md' + - Fixtures: 'fixtures.md' + - Parameterized Tests: 'parameterized.md' + - Organizing Tests: 'organizing_tests.md' + - Test Coverage: 'test_coverage.md' + - Recap Puzzle: 'find_pairs.md' + - 'Appendix: Quotes': 'quotes.md' + diff --git a/mobydick/__init__.py b/mobydick/__init__.py deleted file mode 100644 index b0179ee..0000000 --- a/mobydick/__init__.py +++ /dev/null @@ -1,2 +0,0 @@ - -from .word_counter import TextCorpus, count_word diff --git a/mobydick/word_counter.py b/mobydick/word_counter.py new file mode 100644 index 0000000..7621529 --- /dev/null +++ b/mobydick/word_counter.py @@ -0,0 +1,32 @@ +#!/usr/bin/env python +""" +Code that is being tested +""" + +def split_to_words(text): + '''split a string into tokens''' + if type(text) != str: + raise TypeError('accepts only string input.') + words = text.split(' ') + return words + +def count_words(text): + '''count number of words in a text''' + words = split_to_words(text) + return len(words) + +def count_word(text, word): + '''count the frequency of a word in a text''' + words = split_to_words(text) + return words.count(word) + +def count_words_dict(text): + '''Returns a dictionary of word counts''' + words = split_to_words(text) + d = {} + + for word in words: + d.setdefault(word, 0) + d[word] += 1 + + return d diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000..76e4177 --- /dev/null +++ b/requirements.txt @@ -0,0 +1,7 @@ +Markdown==3.1.1 +mkdocs==1.0.4 +mkdocs-material==4.6.0 +mkdocs-git-revision-date-localized-plugin==0.4.5 +mkdocs-minify-plugin==0.2.1 +pytest +pytest-cov diff --git a/test/test_border_cases.py b/test/test_border_cases.py index 13255db..87ce03d 100644 --- a/test/test_border_cases.py +++ b/test/test_border_cases.py @@ -4,46 +4,45 @@ TASK: fill in the gaps, so that all tests pass """ -from word_counter import count_words import pytest +from mobydick.word_counter import count_words -class TestBorderCases: - def test_empty(self): - """Empty input works""" - text = '' - assert count_words(text) == _____ +def test_empty(): + """Empty input works""" + text = '' + assert count_words(text) == _____ - def test_smallest(self): - """Minimal string works.""" - text = "whale" - assert ____ == ____ +def test_smallest(): + """Minimal string works.""" + text = "whale" + assert ____ == ____ - def test_typical(self): - """Representative input works.""" - text = "whale eats captain" - assert ____ +def test_typical(): + """Representative input works.""" + text = "whale eats captain" + assert ____ - def test_wrong_input(self): - """Non-string fails with a specific error""" - with pytest.raises(_____) as e_info: - count_words(777) +def test_wrong_input(): + """Non-string fails with a specific error""" + with pytest.raises(_____) as e_info: + count_words(777) - def test_biggest(self): - """An entire book works.""" - text = open('mobydick_full.txt').read() - assert _____ > 200000 +def test_biggest(): + """An entire book works.""" + text = open('mobydick_full.txt').read() + assert _____ > 200000 - def test_nasty1(self): - text = """you haint no objections to sharing a harpooneer's blanket, +def test_nasty1(): + text = """you haint no objections to sharing a harpooneer's blanket, have ye? I s'pose you are goin' a-whalin', so you'd better get used to that sort of thing.""" - assert count_words(text) == _____ - - def test_nasty2(self): - """Another ugly data example works.""" - text = """That #~&%* program still doesn't work! - I already de-bugged it 3 times, and still numpy.array keeps throwing AttributeErrors. - What should I do?""" - _____ + assert count_words(text) == _____ + +def test_nasty2(): + """Another ugly data example works.""" + text = """That #~&%* program still doesn't work! +I already de-bugged it 3 times, and still numpy.array keeps throwing AttributeErrors. +What should I do?""" + _____ diff --git a/test/test_broken_code.py b/test/test_broken_code.py index 88d0105..7d72213 100644 --- a/test/test_broken_code.py +++ b/test/test_broken_code.py @@ -2,10 +2,10 @@ Example of test that fails because of broken code. """ -from word_counter import count_words +from mobydick.word_counter import count_words def test_count_words_tabs(): """words are separated by tabs as well""" - text = "the\twhite\whale" + text = "the\twhite\thale" assert count_words(text) == 3 diff --git a/test/test_broken_test.py b/test/test_broken_test.py index 4209ee8..f19de28 100644 --- a/test/test_broken_test.py +++ b/test/test_broken_test.py @@ -2,7 +2,7 @@ Example of test that fails because of a broken test. """ -from word_counter import count_words +from mobydick.word_counter import count_words def test_words(): diff --git a/test/test_fixtures.py b/test/test_fixtures.py deleted file mode 100644 index 55e8a2c..0000000 --- a/test/test_fixtures.py +++ /dev/null @@ -1,28 +0,0 @@ -# -# example of tests with fixtures -# - -from word_counter import TextBody - - -def set_up(self): - """Prepare before each test""" - MOBYDICK_SUMMARY = open('../test_data/mobydick_summary.txt').read() - self.text = TextBody(MOBYDICK_SUMMARY) - -def test_count_months(self): - self.assertEqual(self.counter.count_word("months"), 1) - -def test_count_the(self): - """Count word in a longer text""" - self.assertEqual(self.counter.count_word("the"), 6) - -def test_word_number_text(): - """Count words in a text paragraph""" - text = TextBody(MOBYDICK_SUMMARY) - assert_equal(text.word_number, 54) - - -def tearDown(self): - """Clean up after a test has passed or failed.""" - pass diff --git a/test/test_parameterized.py b/test/test_parameterized.py index f65cd88..e925eac 100644 --- a/test/test_parameterized.py +++ b/test/test_parameterized.py @@ -1,7 +1,6 @@ +from mobydick.word_counter import count_words_dict -from word_counter import count_words_dict - -MOBYDICK_SUMMARY = open('../data/mobydick_summary.txt').read() +MOBYDICK_SUMMARY = open('./data/mobydick_summary.txt').read() PAIRS = [ @@ -15,6 +14,6 @@ def test_count_words_dict(): - counts = count_words_dict(text) + counts = count_words_dict(MOBYDICK_SUMMARY) for word, number in PAIRS: assert counts[word] == number diff --git a/test/test_unit_test.py b/test/test_unit_test.py index 0880df7..6d5d5ee 100644 --- a/test/test_unit_test.py +++ b/test/test_unit_test.py @@ -2,12 +2,10 @@ Example of a Unit Test """ -from word_counter import count_words +from mobydick.word_counter import count_words, split_to_words -class TestMobyDick: - - def test_count_words(self): - """Count words in a short sentence""" - n = count_words("Call me Ishmael") - assert n == 3 +def test_count_words(): + """Count words in a short sentence""" + text = "Call me Ishmael" + assert count_words(text) == 3 diff --git a/test/word_counter.py b/test/word_counter.py deleted file mode 100644 index af7a7d7..0000000 --- a/test/word_counter.py +++ /dev/null @@ -1,16 +0,0 @@ -""" -Code that is being tested -""" - -def count_words(text): - if type(text) != str: - raise TypeError('word counter accepts only string input.') - words = text.split(' ') - return len(words) - - -def count_words_dict(text, n): - '''Returns the n most frequent words.''' - d = {'dummy': 1} - ... - return d