Merge branch 'chapter/09-shared-parts'
This commit is contained in:
commit
a8f8ee6bc5
15
Pipfile
15
Pipfile
|
@ -1,15 +0,0 @@
|
|||
[[source]]
|
||||
name = "pypi"
|
||||
url = "https://pypi.org/simple"
|
||||
verify_ssl = true
|
||||
|
||||
[dev-packages]
|
||||
|
||||
[packages]
|
||||
pytest = "*"
|
||||
pytest-bdd = "*"
|
||||
requests = "*"
|
||||
selenium = "*"
|
||||
|
||||
[requires]
|
||||
python_version = "3.8"
|
|
@ -1,203 +0,0 @@
|
|||
{
|
||||
"_meta": {
|
||||
"hash": {
|
||||
"sha256": "77217213ef2017abdfdad9b28716599c9f2748f9df7bab38aec5cb905509cc8b"
|
||||
},
|
||||
"pipfile-spec": 6,
|
||||
"requires": {
|
||||
"python_version": "3.8"
|
||||
},
|
||||
"sources": [
|
||||
{
|
||||
"name": "pypi",
|
||||
"url": "https://pypi.org/simple",
|
||||
"verify_ssl": true
|
||||
}
|
||||
]
|
||||
},
|
||||
"default": {
|
||||
"attrs": {
|
||||
"hashes": [
|
||||
"sha256:149e90d6d8ac20db7a955ad60cf0e6881a3f20d37096140088356da6c716b0b1",
|
||||
"sha256:ef6aaac3ca6cd92904cdd0d83f629a15f18053ec84e6432106f7a4d04ae4f5fb"
|
||||
],
|
||||
"version": "==21.2.0"
|
||||
},
|
||||
"certifi": {
|
||||
"hashes": [
|
||||
"sha256:2bbf76fd432960138b3ef6dda3dde0544f27cbf8546c458e60baf371917ba9ee",
|
||||
"sha256:50b1e4f8446b06f41be7dd6338db18e0990601dce795c2b1686458aa7e8fa7d8"
|
||||
],
|
||||
"version": "==2021.5.30"
|
||||
},
|
||||
"chardet": {
|
||||
"hashes": [
|
||||
"sha256:0d6f53a15db4120f2b08c94f11e7d93d2c911ee118b6b30a04ec3ee8310179fa",
|
||||
"sha256:f864054d66fd9118f2e67044ac8981a54775ec5b67aed0441892edb553d21da5"
|
||||
],
|
||||
"version": "==4.0.0"
|
||||
},
|
||||
"glob2": {
|
||||
"hashes": [
|
||||
"sha256:85c3dbd07c8aa26d63d7aacee34fa86e9a91a3873bc30bf62ec46e531f92ab8c"
|
||||
],
|
||||
"version": "==0.7"
|
||||
},
|
||||
"idna": {
|
||||
"hashes": [
|
||||
"sha256:b307872f855b18632ce0c21c5e45be78c0ea7ae4c15c828c20788b26921eb3f6",
|
||||
"sha256:b97d804b1e9b523befed77c48dacec60e6dcb0b5391d57af6a65a312a90648c0"
|
||||
],
|
||||
"version": "==2.10"
|
||||
},
|
||||
"iniconfig": {
|
||||
"hashes": [
|
||||
"sha256:011e24c64b7f47f6ebd835bb12a743f2fbe9a26d4cecaa7f53bc4f35ee9da8b3",
|
||||
"sha256:bc3af051d7d14b2ee5ef9969666def0cd1a000e121eaea580d4a313df4b37f32"
|
||||
],
|
||||
"version": "==1.1.1"
|
||||
},
|
||||
"mako": {
|
||||
"hashes": [
|
||||
"sha256:17831f0b7087c313c0ffae2bcbbd3c1d5ba9eeac9c38f2eb7b50e8c99fe9d5ab",
|
||||
"sha256:aea166356da44b9b830c8023cd9b557fa856bd8b4035d6de771ca027dfc5cc6e"
|
||||
],
|
||||
"version": "==1.1.4"
|
||||
},
|
||||
"markupsafe": {
|
||||
"hashes": [
|
||||
"sha256:01a9b8ea66f1658938f65b93a85ebe8bc016e6769611be228d797c9d998dd298",
|
||||
"sha256:023cb26ec21ece8dc3907c0e8320058b2e0cb3c55cf9564da612bc325bed5e64",
|
||||
"sha256:0446679737af14f45767963a1a9ef7620189912317d095f2d9ffa183a4d25d2b",
|
||||
"sha256:0717a7390a68be14b8c793ba258e075c6f4ca819f15edfc2a3a027c823718567",
|
||||
"sha256:0955295dd5eec6cb6cc2fe1698f4c6d84af2e92de33fbcac4111913cd100a6ff",
|
||||
"sha256:10f82115e21dc0dfec9ab5c0223652f7197feb168c940f3ef61563fc2d6beb74",
|
||||
"sha256:1d609f577dc6e1aa17d746f8bd3c31aa4d258f4070d61b2aa5c4166c1539de35",
|
||||
"sha256:2ef54abee730b502252bcdf31b10dacb0a416229b72c18b19e24a4509f273d26",
|
||||
"sha256:3c112550557578c26af18a1ccc9e090bfe03832ae994343cfdacd287db6a6ae7",
|
||||
"sha256:47ab1e7b91c098ab893b828deafa1203de86d0bc6ab587b160f78fe6c4011f75",
|
||||
"sha256:49e3ceeabbfb9d66c3aef5af3a60cc43b85c33df25ce03d0031a608b0a8b2e3f",
|
||||
"sha256:4efca8f86c54b22348a5467704e3fec767b2db12fc39c6d963168ab1d3fc9135",
|
||||
"sha256:53edb4da6925ad13c07b6d26c2a852bd81e364f95301c66e930ab2aef5b5ddd8",
|
||||
"sha256:594c67807fb16238b30c44bdf74f36c02cdf22d1c8cda91ef8a0ed8dabf5620a",
|
||||
"sha256:611d1ad9a4288cf3e3c16014564df047fe08410e628f89805e475368bd304914",
|
||||
"sha256:6557b31b5e2c9ddf0de32a691f2312a32f77cd7681d8af66c2692efdbef84c18",
|
||||
"sha256:693ce3f9e70a6cf7d2fb9e6c9d8b204b6b39897a2c4a1aa65728d5ac97dcc1d8",
|
||||
"sha256:6a7fae0dd14cf60ad5ff42baa2e95727c3d81ded453457771d02b7d2b3f9c0c2",
|
||||
"sha256:6c4ca60fa24e85fe25b912b01e62cb969d69a23a5d5867682dd3e80b5b02581d",
|
||||
"sha256:7d91275b0245b1da4d4cfa07e0faedd5b0812efc15b702576d103293e252af1b",
|
||||
"sha256:905fec760bd2fa1388bb5b489ee8ee5f7291d692638ea5f67982d968366bef9f",
|
||||
"sha256:97383d78eb34da7e1fa37dd273c20ad4320929af65d156e35a5e2d89566d9dfb",
|
||||
"sha256:984d76483eb32f1bcb536dc27e4ad56bba4baa70be32fa87152832cdd9db0833",
|
||||
"sha256:a30e67a65b53ea0a5e62fe23682cfe22712e01f453b95233b25502f7c61cb415",
|
||||
"sha256:ab3ef638ace319fa26553db0624c4699e31a28bb2a835c5faca8f8acf6a5a902",
|
||||
"sha256:b2f4bf27480f5e5e8ce285a8c8fd176c0b03e93dcc6646477d4630e83440c6a9",
|
||||
"sha256:b7f2d075102dc8c794cbde1947378051c4e5180d52d276987b8d28a3bd58c17d",
|
||||
"sha256:be98f628055368795d818ebf93da628541e10b75b41c559fdf36d104c5787066",
|
||||
"sha256:d7f9850398e85aba693bb640262d3611788b1f29a79f0c93c565694658f4071f",
|
||||
"sha256:f5653a225f31e113b152e56f154ccbe59eeb1c7487b39b9d9f9cdb58e6c79dc5",
|
||||
"sha256:f826e31d18b516f653fe296d967d700fddad5901ae07c622bb3705955e1faa94",
|
||||
"sha256:f8ba0e8349a38d3001fae7eadded3f6606f0da5d748ee53cc1dab1d6527b9509",
|
||||
"sha256:f9081981fe268bd86831e5c75f7de206ef275defcb82bc70740ae6dc507aee51",
|
||||
"sha256:fa130dd50c57d53368c9d59395cb5526eda596d3ffe36666cd81a44d56e48872"
|
||||
],
|
||||
"version": "==2.0.1"
|
||||
},
|
||||
"packaging": {
|
||||
"hashes": [
|
||||
"sha256:5b327ac1320dc863dca72f4514ecc086f31186744b84a230374cc1fd776feae5",
|
||||
"sha256:67714da7f7bc052e064859c05c595155bd1ee9f69f76557e21f051443c20947a"
|
||||
],
|
||||
"version": "==20.9"
|
||||
},
|
||||
"parse": {
|
||||
"hashes": [
|
||||
"sha256:9ff82852bcb65d139813e2a5197627a94966245c897796760a3a2a8eb66f020b"
|
||||
],
|
||||
"version": "==1.19.0"
|
||||
},
|
||||
"parse-type": {
|
||||
"hashes": [
|
||||
"sha256:089a471b06327103865dfec2dd844230c3c658a4a1b5b4c8b6c16c8f77577f9e",
|
||||
"sha256:7f690b18d35048c15438d6d0571f9045cffbec5907e0b1ccf006f889e3a38c0b"
|
||||
],
|
||||
"version": "==0.5.2"
|
||||
},
|
||||
"pluggy": {
|
||||
"hashes": [
|
||||
"sha256:15b2acde666561e1298d71b523007ed7364de07029219b604cf808bfa1c765b0",
|
||||
"sha256:966c145cd83c96502c3c3868f50408687b38434af77734af1e9ca461a4081d2d"
|
||||
],
|
||||
"version": "==0.13.1"
|
||||
},
|
||||
"py": {
|
||||
"hashes": [
|
||||
"sha256:21b81bda15b66ef5e1a777a21c4dcd9c20ad3efd0b3f817e7a809035269e1bd3",
|
||||
"sha256:3b80836aa6d1feeaa108e046da6423ab8f6ceda6468545ae8d02d9d58d18818a"
|
||||
],
|
||||
"version": "==1.10.0"
|
||||
},
|
||||
"pyparsing": {
|
||||
"hashes": [
|
||||
"sha256:c203ec8783bf771a155b207279b9bccb8dea02d8f0c9e5f8ead507bc3246ecc1",
|
||||
"sha256:ef9d7589ef3c200abe66653d3f1ab1033c3c419ae9b9bdb1240a85b024efc88b"
|
||||
],
|
||||
"version": "==2.4.7"
|
||||
},
|
||||
"pytest": {
|
||||
"hashes": [
|
||||
"sha256:671238a46e4df0f3498d1c3270e5deb9b32d25134c99b7d75370a68cfbe9b634",
|
||||
"sha256:6ad9c7bdf517a808242b998ac20063c41532a570d088d77eec1ee12b0b5574bc"
|
||||
],
|
||||
"index": "pypi",
|
||||
"version": "==6.2.3"
|
||||
},
|
||||
"pytest-bdd": {
|
||||
"hashes": [
|
||||
"sha256:74ea5a147ea558c99ae83d838e6acbe5c9e6843884a958f8231615d96838733d",
|
||||
"sha256:982489f2f036c7561affe4eeb5b392a37e1ace2a9f260cad747b1c8119e63cfd"
|
||||
],
|
||||
"index": "pypi",
|
||||
"version": "==4.0.2"
|
||||
},
|
||||
"requests": {
|
||||
"hashes": [
|
||||
"sha256:27973dd4a904a4f13b263a19c866c13b92a39ed1c964655f025f3f8d3d75b804",
|
||||
"sha256:c210084e36a42ae6b9219e00e48287def368a26d03a048ddad7bfee44f75871e"
|
||||
],
|
||||
"index": "pypi",
|
||||
"version": "==2.25.1"
|
||||
},
|
||||
"selenium": {
|
||||
"hashes": [
|
||||
"sha256:2d7131d7bc5a5b99a2d9b04aaf2612c411b03b8ca1b1ee8d3de5845a9be2cb3c",
|
||||
"sha256:deaf32b60ad91a4611b98d8002757f29e6f2c2d5fcaf202e1c9ad06d6772300d"
|
||||
],
|
||||
"index": "pypi",
|
||||
"version": "==3.141.0"
|
||||
},
|
||||
"six": {
|
||||
"hashes": [
|
||||
"sha256:1e61c37477a1626458e36f7b1d82aa5c9b094fa4802892072e49de9c60c4c926",
|
||||
"sha256:8abb2f1d86890a2dfb989f9a77cfcfd3e47c2a354b01111771326f8aa26e0254"
|
||||
],
|
||||
"version": "==1.16.0"
|
||||
},
|
||||
"toml": {
|
||||
"hashes": [
|
||||
"sha256:806143ae5bfb6a3c6e736a764057db0e6a0e05e338b5630894a5f779cabb4f9b",
|
||||
"sha256:b3bda1d108d5dd99f4a20d24d9c348e91c4db7ab1b749200bded2f839ccbe68f"
|
||||
],
|
||||
"version": "==0.10.2"
|
||||
},
|
||||
"urllib3": {
|
||||
"hashes": [
|
||||
"sha256:753a0374df26658f99d826cfe40394a686d05985786d946fbe4165b5148f5a7c",
|
||||
"sha256:a7acd0977125325f516bda9735fa7142b909a8d01e8b2e4c8108d0984e6e0098"
|
||||
],
|
||||
"index": "pypi",
|
||||
"version": "==1.26.5"
|
||||
}
|
||||
},
|
||||
"develop": {}
|
||||
}
|
179
README.md
179
README.md
|
@ -1,40 +1,165 @@
|
|||
# tau-pytest-bdd
|
||||
|
||||
This repository contains example code for the
|
||||
*Behavior-Driven Python with pytest-bdd* course
|
||||
from [Test Automation University](https://testautomationu.applitools.com/).
|
||||
There is a branch for each chapter of the course showing the state of the code at the completion of the chapter.
|
||||
|
||||
## Version 4 Warning
|
||||
The TAU course was developed with `pytest-bdd` version 3.
|
||||
Unfortunately, **the version 4 update has incompatible changes.**
|
||||
`@given` methods must now include a `target_fixture` parameter in order to work like pytest fixtures.
|
||||
The TAU videos and transcripts use the old style of code,
|
||||
but the example code here now uses the new style of code.
|
||||
Below is an example of the new style of code needed:
|
||||
|
||||
```python
|
||||
@given("the basket has 2 cucumbers", target_fixture='basket')
|
||||
def basket():
|
||||
return CucumberBasket(initial_count=2)
|
||||
```
|
||||
## Repository Purpose
|
||||
|
||||
## Setup
|
||||
This project requires an up-to-date version of Python 3.
|
||||
It also uses [pipenv](https://pipenv.readthedocs.io/) to manage packages.
|
||||
The best way to learn pytest is through hands-on coding.
|
||||
In the first lesson of the course, you will create a new Python project for test cases.
|
||||
(That project will *not* be the same as this repository.)
|
||||
Each chapter then introduces new concepts and provides coding instructions for your project.
|
||||
If you code along with each chapter,
|
||||
then you will have a complete, functioning test automation project by the end of the course.
|
||||
|
||||
This repository provides all example code for the project.
|
||||
If you get stuck while building your own project,
|
||||
compare your code to the example code in this repository.
|
||||
However, try to avoid blindly copying code from the repository into your project.
|
||||
Take the time to learn the concepts and code presented in each chapter.
|
||||
|
||||
|
||||
## Repository Branches
|
||||
|
||||
* Each `chapter/*` branch contains the state of the code for each chapter
|
||||
* The `main` branch contains the final state of the code at the end of the course
|
||||
|
||||
|
||||
## Python Setup
|
||||
|
||||
Python setup can be complicated.
|
||||
This section documents how to set up your machine for Python test automation development.
|
||||
|
||||
### Python Installation and Tools
|
||||
|
||||
You can complete this course using any OS: Windows, macOS, Linux, etc.
|
||||
|
||||
This course requires Python 3.
|
||||
You can download the latest Python version from [Python.org](https://www.python.org/downloads/).
|
||||
Follow the appropriate installation instructions for your operating system.
|
||||
|
||||
You should have basic Python programming skills before attempting this course.
|
||||
Learning the language is always a prerequisite for learning automation.
|
||||
If you need help learning Python, check out this article:
|
||||
[How Do I Start Learning Python?](https://automationpanda.com/2020/02/18/how-do-i-start-learning-python/)
|
||||
|
||||
You should also have a good Python editor/IDE.
|
||||
Good choices include [PyCharm](https://www.jetbrains.com/pycharm/)
|
||||
and [Visual Studio Code](https://code.visualstudio.com/docs/languages/python).
|
||||
|
||||
You will also need [Git](https://git-scm.com/) if you want to clone this repository locally.
|
||||
If you are new to Git, [try learning the basics](https://try.github.io/).
|
||||
|
||||
For Web UI tests, install the appropriate browser and WebDriver executable.
|
||||
These tests use Firefox and [geckodriver](https://github.com/mozilla/geckodriver/releases).
|
||||
|
||||
|
||||
### Python Installation Troubleshooting
|
||||
|
||||
Unfortunately, installing Python properly can be complicated,
|
||||
especially if Python was previously installed on your machine.
|
||||
To verify your Python installation, enter `python --version` at the command line.
|
||||
You should see the proper version printed.
|
||||
|
||||
If the `python` command doesn't work or doesn’t print the expected version number,
|
||||
then try using the `python3` command instead.
|
||||
If that still doesn't work,
|
||||
then the correct Python installation might not be included in your system path.
|
||||
Find the directory into which Python was installed,
|
||||
manually add it to the system path,
|
||||
relaunch the command line,
|
||||
and try running Python again.
|
||||
|
||||
* [System Path Instructions for Windows](https://geek-university.com/python/add-python-to-the-windows-path/)
|
||||
* [System Path Instructions for macOS](https://www.educative.io/edpresso/how-to-add-python-to-the-path-variable-in-mac)
|
||||
* [System Path Instructions for Linux](https://www.computerhope.com/issues/ch001647.htm)
|
||||
|
||||
### Python Packages
|
||||
|
||||
This course will use a handful of third-party packages that are *not* part of the Python Standard Library.
|
||||
They must be installed separately using `pip`, the standard Python package installer.
|
||||
You can install them all before you create your test project,
|
||||
or you can install them as you complete each chapter in the course.
|
||||
|
||||
To install each package, enter `pip install <package-name>` at the command line.
|
||||
For example: `pip install pytest`.
|
||||
If you already have a package installed but need to upgrade its version,
|
||||
run `pip install --upgrade <package-name>`.
|
||||
|
||||
Please note that if you need to use the `python3` command to run Python,
|
||||
then you might also need to use the `pip3` command in lieu of `pip`.
|
||||
|
||||
### Virtual Environments
|
||||
|
||||
Running `pip install` will install the pytest package globally for the whole system.
|
||||
Installing Python packages globally is okay for this course,
|
||||
but it typically isn't a best practice in the "read world."
|
||||
Instead, each project should manage its own dependencies locally using a virtual environment.
|
||||
Virtual environments let projects avoid unnecessary dependencies and version mismatches.
|
||||
|
||||
For simplicity, this course will not use or teach virtual environments.
|
||||
If you would like to learn virtual environments on your own, then RealPython's article
|
||||
[Python Virtual Environments: A Primer](https://realpython.com/python-virtual-environments-a-primer/)
|
||||
is an excellent place to start.
|
||||
|
||||
### Package Versions
|
||||
|
||||
The [`requirements.txt`](requirements.txt) file contains the versions for each package used in this course.
|
||||
|
||||
To set up this project on your local machine:
|
||||
1. Clone it from this GitHub repository.
|
||||
2. Run `pipenv install` from the command line in the project's root directory.
|
||||
3. For Web UI tests, install the appropriate browser and WebDriver executable.
|
||||
* These tests use Firefox and [geckodriver](https://github.com/mozilla/geckodriver/releases).
|
||||
|
||||
## Running Tests
|
||||
Run tests simply using the `pytest` command.
|
||||
Depending upon your environment, it may be better to use `python -m pytest`.
|
||||
If you are using `pipenv`, then run `pipenv run python -m pytest`.
|
||||
Use the "-k" option to filter tests by tags.
|
||||
|
||||
## More Info
|
||||
For the best experience, take the full TAU course chapter-by-chapter.
|
||||
Check out the branch for each chapter and follow along.
|
||||
To run the example tests from the command line, run `python -m pytest` from the project root directory.
|
||||
This command will discover and run all tests in the project.
|
||||
|
||||
You can also run tests using the shorter `pytest` command.
|
||||
However, I recommend always using the lengthier `python -m pytest` command.
|
||||
The lengthier command automatically adds the current directory to `sys.path`
|
||||
so that all modules in the project can be discovered.
|
||||
|
||||
The pytest command has several command line options.
|
||||
Course material will cover many of them.
|
||||
Check out the [Usage and Invocations](https://docs.pytest.org/en/stable/usage.html) page
|
||||
for complete documentation.
|
||||
|
||||
*Warning:*
|
||||
If you attempt to run tests from this example project,
|
||||
make sure to checkout the correct branch first!
|
||||
|
||||
|
||||
## Additional Resources
|
||||
|
||||
Python links:
|
||||
|
||||
* [Python.org](https://www.python.org/)
|
||||
* [pytest.org](https://docs.pytest.org/)
|
||||
* [How Do I Start Learning Python?](https://automationpanda.com/2020/02/18/how-do-i-start-learning-python/)
|
||||
* [Python Virtual Environments: A Primer](https://realpython.com/python-virtual-environments-a-primer/)
|
||||
* [Effective Python Testing with Pytest](https://realpython.com/pytest-python-testing/)
|
||||
* [Automation Panda's Python Page](https://automationpanda.com/python/)
|
||||
|
||||
Books:
|
||||
|
||||
* [Python Testing with pytest](https://pragprog.com/titles/bopytest/) by Brian Okken
|
||||
* [pytest Quick Start Guide](https://www.packtpub.com/web-development/pytest-quick-start-guide) by Bruno Oliveira
|
||||
* [Test-Driven Development with Python](https://www.obeythetestinggoat.com/) by Harry J.W. Percival
|
||||
|
||||
Related TAU courses:
|
||||
|
||||
* [Python Programming](https://testautomationu.applitools.com/python-tutorial/)
|
||||
* [Introduction to pytest](https://testautomationu.applitools.com/pytest-tutorial/)
|
||||
* [Selenium WebDriver with Python](https://testautomationu.applitools.com/selenium-webdriver-python-tutorial/)
|
||||
* [Automated Visual Testing with Python](https://testautomationu.applitools.com/visual-testing-python/)
|
||||
|
||||
|
||||
## About the Author
|
||||
|
||||
This course was written and delivered by **Andrew Knight** (aka *Pandy*), the "Automation Panda".
|
||||
Andy is a Pythonista who specializes in testing and automation.
|
||||
|
||||
* Blog: [AutomationPanda.com](https://automationpanda.com/)
|
||||
* Twitter: [@AutomationPanda](https://twitter.com/AutomationPanda)
|
||||
* LinkedIn: [andrew-leland-knight](https://www.linkedin.com/in/andrew-leland-knight/)
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
[pytest]
|
||||
junit_family = xunit2
|
||||
markers =
|
||||
add
|
||||
cucumber-basket
|
||||
|
@ -7,4 +6,4 @@ markers =
|
|||
remove
|
||||
service
|
||||
web
|
||||
testpaths = tests
|
||||
testpaths = tests
|
|
@ -0,0 +1,4 @@
|
|||
pytest==7.4.0
|
||||
pytest-bdd==6.1.1
|
||||
requests==2.31.0
|
||||
selenium==4.10.0
|
|
@ -20,4 +20,4 @@ Feature: DuckDuckGo Instant Answer API
|
|||
| phrase |
|
||||
| peach |
|
||||
| pineapple |
|
||||
| papaya |
|
||||
| papaya |
|
|
@ -32,4 +32,4 @@ def browser():
|
|||
|
||||
@given('the DuckDuckGo home page is displayed', target_fixture='ddg_home')
|
||||
def ddg_home(browser):
|
||||
browser.get(DUCKDUCKGO_HOME)
|
||||
browser.get(DUCKDUCKGO_HOME)
|
|
@ -3,40 +3,40 @@ from pytest_bdd import scenarios, parsers, given, when, then
|
|||
from cucumbers import CucumberBasket
|
||||
|
||||
|
||||
EXTRA_TYPES = {
|
||||
'Number': int,
|
||||
}
|
||||
scenarios('../features/cucumbers.feature')
|
||||
|
||||
|
||||
CONVERTERS = {
|
||||
'initial': int,
|
||||
'some': int,
|
||||
'total': int,
|
||||
'initial': int,
|
||||
'some': int,
|
||||
'total': int,
|
||||
}
|
||||
|
||||
|
||||
scenarios('../features/cucumbers.feature', example_converters=CONVERTERS)
|
||||
|
||||
|
||||
@given(parsers.cfparse('the basket has "{initial:Number}" cucumbers', extra_types=EXTRA_TYPES), target_fixture='basket')
|
||||
@given('the basket has "<initial>" cucumbers', target_fixture='basket')
|
||||
@given(
|
||||
parsers.parse('the basket has "{initial}" cucumbers'),
|
||||
target_fixture='basket',
|
||||
converters=CONVERTERS)
|
||||
def basket(initial):
|
||||
return CucumberBasket(initial_count=initial)
|
||||
return CucumberBasket(initial_count=initial)
|
||||
|
||||
|
||||
@when(parsers.cfparse('"{some:Number}" cucumbers are added to the basket', extra_types=EXTRA_TYPES))
|
||||
@when('"<some>" cucumbers are added to the basket')
|
||||
@when(
|
||||
parsers.parse('"{some}" cucumbers are added to the basket'),
|
||||
converters=CONVERTERS)
|
||||
def add_cucumbers(basket, some):
|
||||
basket.add(some)
|
||||
basket.add(some)
|
||||
|
||||
|
||||
@when(parsers.cfparse('"{some:Number}" cucumbers are removed from the basket', extra_types=EXTRA_TYPES))
|
||||
@when('"<some>" cucumbers are removed from the basket')
|
||||
@when(
|
||||
parsers.parse('"{some}" cucumbers are removed from the basket'),
|
||||
converters=CONVERTERS)
|
||||
def remove_cucumbers(basket, some):
|
||||
basket.remove(some)
|
||||
basket.remove(some)
|
||||
|
||||
|
||||
@then(parsers.cfparse('the basket contains "{total:Number}" cucumbers', extra_types=EXTRA_TYPES))
|
||||
@then('the basket contains "<total>" cucumbers')
|
||||
@then(
|
||||
parsers.parse('the basket contains "{total}" cucumbers'),
|
||||
converters=CONVERTERS)
|
||||
def basket_has_total(basket, total):
|
||||
assert basket.count == total
|
||||
assert basket.count == total
|
||||
|
|
|
@ -16,26 +16,39 @@ DUCKDUCKGO_API = 'https://api.duckduckgo.com/'
|
|||
|
||||
# Scenarios
|
||||
|
||||
scenarios('../features/service.feature', example_converters=dict(phrase=str))
|
||||
|
||||
scenarios('../features/service.feature')
|
||||
|
||||
CONVERTERS = {
|
||||
'code': int,
|
||||
'phrase': str,
|
||||
}
|
||||
|
||||
|
||||
# Given Steps
|
||||
|
||||
@given('the DuckDuckGo API is queried with "<phrase>"', target_fixture='ddg_response')
|
||||
@given(
|
||||
parsers.parse('the DuckDuckGo API is queried with "{phrase}"'),
|
||||
target_fixture='ddg_response',
|
||||
converters=CONVERTERS)
|
||||
def ddg_response(phrase):
|
||||
params = {'q': phrase, 'format': 'json'}
|
||||
response = requests.get(DUCKDUCKGO_API, params=params)
|
||||
return response
|
||||
params = {'q': phrase, 'format': 'json'}
|
||||
response = requests.get(DUCKDUCKGO_API, params=params)
|
||||
return response
|
||||
|
||||
|
||||
# Then Steps
|
||||
|
||||
@then('the response contains results for "<phrase>"')
|
||||
@then(
|
||||
parsers.parse('the response contains results for "{phrase}"'),
|
||||
converters=CONVERTERS)
|
||||
def ddg_response_contents(ddg_response, phrase):
|
||||
# A more comprehensive test would check 'RelatedTopics' for matching phrases
|
||||
assert phrase.lower() == ddg_response.json()['Heading'].lower()
|
||||
# A more comprehensive test would check 'RelatedTopics' for matching phrases
|
||||
assert phrase.lower() == ddg_response.json()['Heading'].lower()
|
||||
|
||||
|
||||
@then(parsers.parse('the response status code is "{code:d}"'))
|
||||
@then(
|
||||
parsers.parse('the response status code is "{code}"'),
|
||||
converters=CONVERTERS)
|
||||
def ddg_response_code(ddg_response, code):
|
||||
assert ddg_response.status_code == code
|
||||
assert ddg_response.status_code == code
|
||||
|
|
|
@ -12,14 +12,10 @@ Prerequisites:
|
|||
"""
|
||||
|
||||
from pytest_bdd import scenarios, when, then, parsers
|
||||
from selenium.webdriver.common.by import By
|
||||
from selenium.webdriver.common.keys import Keys
|
||||
|
||||
|
||||
# Constants
|
||||
|
||||
DUCKDUCKGO_HOME = 'https://duckduckgo.com/'
|
||||
|
||||
|
||||
# Scenarios
|
||||
|
||||
scenarios('../features/web.feature')
|
||||
|
@ -30,7 +26,7 @@ scenarios('../features/web.feature')
|
|||
@when(parsers.parse('the user searches for "{text}"'))
|
||||
@when(parsers.parse('the user searches for the phrase:\n{text}'))
|
||||
def search_phrase(browser, text):
|
||||
search_input = browser.find_element_by_id('search_form_input_homepage')
|
||||
search_input = browser.find_element(By.NAME, 'q')
|
||||
search_input.send_keys(text + Keys.RETURN)
|
||||
|
||||
|
||||
|
@ -38,8 +34,8 @@ def search_phrase(browser, text):
|
|||
|
||||
@then(parsers.parse('one of the results contains "{phrase}"'))
|
||||
def results_have_one(browser, phrase):
|
||||
xpath = "//div[@id='links']//*[contains(text(), '%s')]" % phrase
|
||||
results = browser.find_elements_by_xpath(xpath)
|
||||
xpath = "//*[@data-testid='result']//*[contains(text(), '%s')]" % phrase
|
||||
results = browser.find_elements(By.XPATH, xpath)
|
||||
assert len(results) > 0
|
||||
|
||||
|
||||
|
@ -48,8 +44,7 @@ def search_results(browser, phrase):
|
|||
# Check search result list
|
||||
# (A more comprehensive test would check results for matching phrases)
|
||||
# (Check the list before the search phrase for correct implicit waiting)
|
||||
links_div = browser.find_element_by_id('links')
|
||||
assert len(links_div.find_elements_by_xpath('//div')) > 0
|
||||
assert len(browser.find_elements(By.CSS_SELECTOR, '[data-testid="result"]')) > 0
|
||||
# Check search phrase
|
||||
search_input = browser.find_element_by_id('search_form_input')
|
||||
search_input = browser.find_element(By.NAME, 'q')
|
||||
assert search_input.get_attribute('value') == phrase
|
||||
|
|
Loading…
Reference in New Issue