getting-started.rst (9504B)
1 .. _get-started: 2 3 Get Started 4 =================================== 5 6 .. _`getstarted`: 7 .. _`installation`: 8 9 Install ``pytest`` 10 ---------------------------------------- 11 12 ``pytest`` requires: Python 3.8+ or PyPy3. 13 14 1. Run the following command in your command line: 15 16 .. code-block:: bash 17 18 pip install -U pytest 19 20 2. Check that you installed the correct version: 21 22 .. code-block:: bash 23 24 $ pytest --version 25 pytest 8.2.1 26 27 .. _`simpletest`: 28 29 Create your first test 30 ---------------------------------------------------------- 31 32 Create a new file called ``test_sample.py``, containing a function, and a test: 33 34 .. code-block:: python 35 36 # content of test_sample.py 37 def func(x): 38 return x + 1 39 40 41 def test_answer(): 42 assert func(3) == 5 43 44 The test 45 46 .. code-block:: pytest 47 48 $ pytest 49 =========================== test session starts ============================ 50 platform linux -- Python 3.x.y, pytest-8.x.y, pluggy-1.x.y 51 rootdir: /home/sweet/project 52 collected 1 item 53 54 test_sample.py F [100%] 55 56 ================================= FAILURES ================================= 57 _______________________________ test_answer ________________________________ 58 59 def test_answer(): 60 > assert func(3) == 5 61 E assert 4 == 5 62 E + where 4 = func(3) 63 64 test_sample.py:6: AssertionError 65 ========================= short test summary info ========================== 66 FAILED test_sample.py::test_answer - assert 4 == 5 67 ============================ 1 failed in 0.12s ============================= 68 69 The ``[100%]`` refers to the overall progress of running all test cases. After it finishes, pytest then shows a failure report because ``func(3)`` does not return ``5``. 70 71 .. note:: 72 73 You can use the ``assert`` statement to verify test expectations. pytest’s :ref:`Advanced assertion introspection <python:assert>` will intelligently report intermediate values of the assert expression so you can avoid the many names :ref:`of JUnit legacy methods <testcase-objects>`. 74 75 Run multiple tests 76 ---------------------------------------------------------- 77 78 ``pytest`` will run all files of the form test_*.py or \*_test.py in the current directory and its subdirectories. More generally, it follows :ref:`standard test discovery rules <test discovery>`. 79 80 81 Assert that a certain exception is raised 82 -------------------------------------------------------------- 83 84 Use the :ref:`raises <assertraises>` helper to assert that some code raises an exception: 85 86 .. code-block:: python 87 88 # content of test_sysexit.py 89 import pytest 90 91 92 def f(): 93 raise SystemExit(1) 94 95 96 def test_mytest(): 97 with pytest.raises(SystemExit): 98 f() 99 100 You can also use the context provided by :ref:`raises <assertraises>` to 101 assert that an expected exception is part of a raised :class:`ExceptionGroup`: 102 103 .. code-block:: python 104 105 # content of test_exceptiongroup.py 106 import pytest 107 108 109 def f(): 110 raise ExceptionGroup( 111 "Group message", 112 [ 113 RuntimeError(), 114 ], 115 ) 116 117 118 def test_exception_in_group(): 119 with pytest.raises(ExceptionGroup) as excinfo: 120 f() 121 assert excinfo.group_contains(RuntimeError) 122 assert not excinfo.group_contains(TypeError) 123 124 Execute the test function with “quiet” reporting mode: 125 126 .. code-block:: pytest 127 128 $ pytest -q test_sysexit.py 129 . [100%] 130 1 passed in 0.12s 131 132 .. note:: 133 134 The ``-q/--quiet`` flag keeps the output brief in this and following examples. 135 136 Group multiple tests in a class 137 -------------------------------------------------------------- 138 139 .. regendoc:wipe 140 141 Once you develop multiple tests, you may want to group them into a class. pytest makes it easy to create a class containing more than one test: 142 143 .. code-block:: python 144 145 # content of test_class.py 146 class TestClass: 147 def test_one(self): 148 x = "this" 149 assert "h" in x 150 151 def test_two(self): 152 x = "hello" 153 assert hasattr(x, "check") 154 155 ``pytest`` discovers all tests following its :ref:`Conventions for Python test discovery <test discovery>`, so it finds both ``test_`` prefixed functions. There is no need to subclass anything, but make sure to prefix your class with ``Test`` otherwise the class will be skipped. We can simply run the module by passing its filename: 156 157 .. code-block:: pytest 158 159 $ pytest -q test_class.py 160 .F [100%] 161 ================================= FAILURES ================================= 162 ____________________________ TestClass.test_two ____________________________ 163 164 self = <test_class.TestClass object at 0xdeadbeef0001> 165 166 def test_two(self): 167 x = "hello" 168 > assert hasattr(x, "check") 169 E AssertionError: assert False 170 E + where False = hasattr('hello', 'check') 171 172 test_class.py:8: AssertionError 173 ========================= short test summary info ========================== 174 FAILED test_class.py::TestClass::test_two - AssertionError: assert False 175 1 failed, 1 passed in 0.12s 176 177 The first test passed and the second failed. You can easily see the intermediate values in the assertion to help you understand the reason for the failure. 178 179 Grouping tests in classes can be beneficial for the following reasons: 180 181 * Test organization 182 * Sharing fixtures for tests only in that particular class 183 * Applying marks at the class level and having them implicitly apply to all tests 184 185 Something to be aware of when grouping tests inside classes is that each test has a unique instance of the class. 186 Having each test share the same class instance would be very detrimental to test isolation and would promote poor test practices. 187 This is outlined below: 188 189 .. regendoc:wipe 190 191 .. code-block:: python 192 193 # content of test_class_demo.py 194 class TestClassDemoInstance: 195 value = 0 196 197 def test_one(self): 198 self.value = 1 199 assert self.value == 1 200 201 def test_two(self): 202 assert self.value == 1 203 204 205 .. code-block:: pytest 206 207 $ pytest -k TestClassDemoInstance -q 208 .F [100%] 209 ================================= FAILURES ================================= 210 ______________________ TestClassDemoInstance.test_two ______________________ 211 212 self = <test_class_demo.TestClassDemoInstance object at 0xdeadbeef0002> 213 214 def test_two(self): 215 > assert self.value == 1 216 E assert 0 == 1 217 E + where 0 = <test_class_demo.TestClassDemoInstance object at 0xdeadbeef0002>.value 218 219 test_class_demo.py:9: AssertionError 220 ========================= short test summary info ========================== 221 FAILED test_class_demo.py::TestClassDemoInstance::test_two - assert 0 == 1 222 1 failed, 1 passed in 0.12s 223 224 Note that attributes added at class level are *class attributes*, so they will be shared between tests. 225 226 Request a unique temporary directory for functional tests 227 -------------------------------------------------------------- 228 229 ``pytest`` provides :std:doc:`Builtin fixtures/function arguments <builtin>` to request arbitrary resources, like a unique temporary directory: 230 231 .. code-block:: python 232 233 # content of test_tmp_path.py 234 def test_needsfiles(tmp_path): 235 print(tmp_path) 236 assert 0 237 238 List the name ``tmp_path`` in the test function signature and ``pytest`` will lookup and call a fixture factory to create the resource before performing the test function call. Before the test runs, ``pytest`` creates a unique-per-test-invocation temporary directory: 239 240 .. code-block:: pytest 241 242 $ pytest -q test_tmp_path.py 243 F [100%] 244 ================================= FAILURES ================================= 245 _____________________________ test_needsfiles ______________________________ 246 247 tmp_path = PosixPath('PYTEST_TMPDIR/test_needsfiles0') 248 249 def test_needsfiles(tmp_path): 250 print(tmp_path) 251 > assert 0 252 E assert 0 253 254 test_tmp_path.py:3: AssertionError 255 --------------------------- Captured stdout call --------------------------- 256 PYTEST_TMPDIR/test_needsfiles0 257 ========================= short test summary info ========================== 258 FAILED test_tmp_path.py::test_needsfiles - assert 0 259 1 failed in 0.12s 260 261 More info on temporary directory handling is available at :ref:`Temporary directories and files <tmp_path handling>`. 262 263 Find out what kind of builtin :ref:`pytest fixtures <fixtures>` exist with the command: 264 265 .. code-block:: bash 266 267 pytest --fixtures # shows builtin and custom fixtures 268 269 Note that this command omits fixtures with leading ``_`` unless the ``-v`` option is added. 270 271 Continue reading 272 ------------------------------------- 273 274 Check out additional pytest resources to help you customize tests for your unique workflow: 275 276 * ":ref:`usage`" for command line invocation examples 277 * ":ref:`existingtestsuite`" for working with preexisting tests 278 * ":ref:`mark`" for information on the ``pytest.mark`` mechanism 279 * ":ref:`fixtures`" for providing a functional baseline to your tests 280 * ":ref:`plugins`" for managing and writing plugins 281 * ":ref:`goodpractices`" for virtualenv and test layouts