<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Test Automation on Testing Observation</title><link>https://chengxiaqiucao.github.io/en/tags/test-automation/</link><description>Recent content in Test Automation on Testing Observation</description><generator>Hugo -- gohugo.io</generator><language>en</language><copyright>|by Daniel Wei</copyright><lastBuildDate>Tue, 24 Sep 2024 13:16:16 +0800</lastBuildDate><atom:link href="https://chengxiaqiucao.github.io/en/tags/test-automation/index.xml" rel="self" type="application/rss+xml"/><item><title>Automatically Specifying Referenceable Fixtures in Pytest</title><link>https://chengxiaqiucao.github.io/en/post/017-pytest%E4%B8%AD%E8%87%AA%E5%8A%A8%E6%8C%87%E5%AE%9A%E5%8F%AF%E5%BC%95%E7%94%A8fixture/</link><pubDate>Tue, 24 Sep 2024 13:16:16 +0800</pubDate><guid>https://chengxiaqiucao.github.io/en/post/017-pytest%E4%B8%AD%E8%87%AA%E5%8A%A8%E6%8C%87%E5%AE%9A%E5%8F%AF%E5%BC%95%E7%94%A8fixture/</guid><description>&lt;img src="https://chengxiaqiucao.github.io/post/017-pytest%E4%B8%AD%E8%87%AA%E5%8A%A8%E6%8C%87%E5%AE%9A%E5%8F%AF%E5%BC%95%E7%94%A8fixture/pytest.webp" alt="Featured image of post Automatically Specifying Referenceable Fixtures in Pytest" />&lt;p>When we use the Pytest framework for Test Automation, its powerful fixtures bring great convenience to the flexible application of the framework. For example, we can use the &lt;code>autouse&lt;/code> attribute of a fixture to make it take effect automatically at different scope levels of test methods. But if we want to reference the return value of a fixture, we usually still have to specify it explicitly, which is a bit inconvenient&lt;/p>
&lt;h2 id="specifying-a-fixture-with-autouse-but-it-still-needs-to-be-explicitly-carried-as-a-parameter-to-be-called">Specifying a Fixture with autouse, but It Still Needs to Be Explicitly Carried as a Parameter to Be Called
&lt;/h2>&lt;p>Take &lt;code>webdriver&lt;/code>, the most commonly used object in &lt;code>Selenium&lt;/code> automation, as an example. When implementing automation, the &lt;code>webdriver&lt;/code> object usually stays in effect throughout the entire execution and is frequently called.&lt;/p>
&lt;p>The usual practice is to write a session-level generic &lt;code>driver&lt;/code> fixture in the &lt;code>conftest.py&lt;/code> file and set &lt;code>autouse&lt;/code> to enabled:&lt;/p>
&lt;p>conftest.py&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;span class="lnt">3
&lt;/span>&lt;span class="lnt">4
&lt;/span>&lt;span class="lnt">5
&lt;/span>&lt;span class="lnt">6
&lt;/span>&lt;span class="lnt">7
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-python" data-lang="python">&lt;span class="line">&lt;span class="cl">&lt;span class="nd">@pytest.fixture&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">scope&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s2">&amp;#34;session&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>&lt;span class="n">autouse&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="kc">True&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="k">def&lt;/span> &lt;span class="nf">driver&lt;/span>&lt;span class="p">():&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">option&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">webdriver&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">ChromeOptions&lt;/span>&lt;span class="p">()&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">driver&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">webdriver&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">Chrome&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">options&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="n">option&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">driver&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">implicitly_wait&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="mi">3&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">driver&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">webdriver&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">Chrome&lt;/span>&lt;span class="p">()&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">yield&lt;/span> &lt;span class="n">driver&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>Then in another test file, when writing the test class and test methods, we can directly reference this &lt;code>driver&lt;/code> fixture&lt;/p>
&lt;p>test_auto_driver.py&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;span class="lnt">3
&lt;/span>&lt;span class="lnt">4
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-python" data-lang="python">&lt;span class="line">&lt;span class="cl">&lt;span class="k">class&lt;/span> &lt;span class="nc">TestDriver&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">def&lt;/span> &lt;span class="nf">Test_open_blog&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="bp">self&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">driver&lt;/span>&lt;span class="p">):&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">driver&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">get&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s2">&amp;#34;https://chengxiaqiucao.github.io/&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">assert&lt;/span> &lt;span class="n">driver&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">title&lt;/span> &lt;span class="o">==&lt;/span> &lt;span class="s2">&amp;#34;秋 草 观 “测” 台&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>But if the whole test project is fairly large and there are many similar test classes and test methods, every time we define a test method we have to specify this generic fixture in order to reference the &lt;code>driver&lt;/code> object. Doesn&amp;rsquo;t that always feel a little inelegant?&lt;/p>
&lt;h2 id="pytest-built-in-fixture-request">Pytest Built-in Fixture: Request
&lt;/h2>&lt;p>Actually, if you have studied how to do parameterization through fixtures, you should know that parameterization via fixtures is accomplished through an internal fixture of pytest called &lt;code>request&lt;/code>. &lt;code>request&lt;/code> should be the most important built-in fixture in pytest. And by using this fixture, we can in fact implicitly pass some generic fixtures to each test class by default&lt;/p>
&lt;h3 id="a-brief-introduction-to-request">A Brief Introduction to request
&lt;/h3>&lt;p>According to the official documentation:&lt;/p>
&lt;p>&lt;img src="https://chengxiaqiucao.github.io/post/017-pytest%E4%B8%AD%E8%87%AA%E5%8A%A8%E6%8C%87%E5%AE%9A%E5%8F%AF%E5%BC%95%E7%94%A8fixture/Pasted-20240924-3_hu_41b71d7a4fc97a6e.webp"
width="1024"
height="924"
srcset="https://chengxiaqiucao.github.io/post/017-pytest%E4%B8%AD%E8%87%AA%E5%8A%A8%E6%8C%87%E5%AE%9A%E5%8F%AF%E5%BC%95%E7%94%A8fixture/Pasted-20240924-3_hu_b33859a1db0bf550.webp 480w, https://chengxiaqiucao.github.io/post/017-pytest%E4%B8%AD%E8%87%AA%E5%8A%A8%E6%8C%87%E5%AE%9A%E5%8F%AF%E5%BC%95%E7%94%A8fixture/Pasted-20240924-3_hu_41b71d7a4fc97a6e.webp 1024w"
loading="lazy"
class="gallery-image"
data-flex-grow="110"
data-flex-basis="265px"
>
&lt;/p>
&lt;blockquote>
&lt;p>&lt;code>request&lt;/code> is a built-in fixture used to provide contextual information about the current test method and to implement parameterization through the &lt;code>param&lt;/code> parameter.&lt;/p>&lt;/blockquote>
&lt;p>With request, we can obtain a great deal of contextual information about the current fixture during runtime, such as the fixture name, path, the current session, module, class information, and so on.&lt;/p>
&lt;p>The figure below shows the attributes of the request object obtained at a breakpoint when referencing a fixture&lt;/p>
&lt;p>&lt;img src="https://chengxiaqiucao.github.io/post/017-pytest%E4%B8%AD%E8%87%AA%E5%8A%A8%E6%8C%87%E5%AE%9A%E5%8F%AF%E5%BC%95%E7%94%A8fixture/Pasted-20240924_hu_60d24be681c8023c.webp"
width="1024"
height="522"
srcset="https://chengxiaqiucao.github.io/post/017-pytest%E4%B8%AD%E8%87%AA%E5%8A%A8%E6%8C%87%E5%AE%9A%E5%8F%AF%E5%BC%95%E7%94%A8fixture/Pasted-20240924_hu_90341fa860686b75.webp 480w, https://chengxiaqiucao.github.io/post/017-pytest%E4%B8%AD%E8%87%AA%E5%8A%A8%E6%8C%87%E5%AE%9A%E5%8F%AF%E5%BC%95%E7%94%A8fixture/Pasted-20240924_hu_60d24be681c8023c.webp 1024w"
loading="lazy"
class="gallery-image"
data-flex-grow="196"
data-flex-basis="470px"
>
&lt;/p>
&lt;p>&lt;img src="https://chengxiaqiucao.github.io/post/017-pytest%E4%B8%AD%E8%87%AA%E5%8A%A8%E6%8C%87%E5%AE%9A%E5%8F%AF%E5%BC%95%E7%94%A8fixture/Pasted-20240924-1_hu_e436021c00586cfb.webp"
width="1024"
height="661"
srcset="https://chengxiaqiucao.github.io/post/017-pytest%E4%B8%AD%E8%87%AA%E5%8A%A8%E6%8C%87%E5%AE%9A%E5%8F%AF%E5%BC%95%E7%94%A8fixture/Pasted-20240924-1_hu_3c253f77b97da64f.webp 480w, https://chengxiaqiucao.github.io/post/017-pytest%E4%B8%AD%E8%87%AA%E5%8A%A8%E6%8C%87%E5%AE%9A%E5%8F%AF%E5%BC%95%E7%94%A8fixture/Pasted-20240924-1_hu_e436021c00586cfb.webp 1024w"
loading="lazy"
class="gallery-image"
data-flex-grow="154"
data-flex-basis="371px"
>
&lt;/p>
&lt;p>So in the example above, as a generic fixture that takes effect at the session level, we can use its session attribute to obtain all the classes in the current session, and then assign the &lt;code>driver&lt;/code> object to the relevant class attributes. In this way, when defining a test class, we no longer need to specify the fixture separately and can reference it directly through the class attribute as needed.&lt;/p>
&lt;h2 id="implementing-automatic-assignment-of-a-fixture-to-class-attributes">Implementing Automatic Assignment of a Fixture to Class Attributes
&lt;/h2>&lt;p>So the code of the above example is modified as follows:&lt;/p>
&lt;p>conftest.py&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;span class="lnt">12
&lt;/span>&lt;span class="lnt">13
&lt;/span>&lt;span class="lnt">14
&lt;/span>&lt;span class="lnt">15
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-python" data-lang="python">&lt;span class="line">&lt;span class="cl">&lt;span class="nd">@pytest.fixture&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">scope&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s2">&amp;#34;session&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>&lt;span class="n">autouse&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="kc">True&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="k">def&lt;/span> &lt;span class="nf">driver&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">request&lt;/span>&lt;span class="p">):&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;&amp;#34;&amp;#34;
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s2"> Automatically apply the fixture and set it as a class attribute of the caller
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s2"> :param request: pytest&amp;#39;s built-in fixture, used to obtain the fixture&amp;#39;s context
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s2"> :return:
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s2"> &amp;#34;&amp;#34;&amp;#34;&lt;/span> &lt;span class="n">driver&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">webdriver&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">Chrome&lt;/span>&lt;span class="p">()&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">try&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">session&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">request&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">node&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">for&lt;/span> &lt;span class="n">item&lt;/span> &lt;span class="ow">in&lt;/span> &lt;span class="n">session&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">items&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="bp">cls&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">item&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">getparent&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">pytest&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">Class&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nb">setattr&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="bp">cls&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">obj&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="s1">&amp;#39;driver&amp;#39;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">driver&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">yield&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">finally&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">driver&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">quit&lt;/span>&lt;span class="p">()&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>Here we add the &lt;code>driver&lt;/code> object as a class attribute, and the fixture itself no longer yields any object as a return value&lt;/p>
&lt;p>Correspondingly, in the test script we can simply use the class attribute directly via &lt;code>self.driver&lt;/code>&lt;/p>
&lt;p>test_auto_driver.py&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;span class="lnt">3
&lt;/span>&lt;span class="lnt">4
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-python" data-lang="python">&lt;span class="line">&lt;span class="cl">&lt;span class="k">class&lt;/span> &lt;span class="nc">TestDriver&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">def&lt;/span> &lt;span class="nf">Test_open_blog&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="bp">self&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">driver&lt;/span>&lt;span class="p">):&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="bp">self&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">driver&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">get&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s2">&amp;#34;https://chengxiaqiucao.github.io/&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">assert&lt;/span> &lt;span class="bp">self&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">driver&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">title&lt;/span> &lt;span class="o">==&lt;/span> &lt;span class="s2">&amp;#34;秋 草 观 “测” 台&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>The execution result: the test case is likewise completed correctly.
&lt;img src="https://chengxiaqiucao.github.io/post/017-pytest%E4%B8%AD%E8%87%AA%E5%8A%A8%E6%8C%87%E5%AE%9A%E5%8F%AF%E5%BC%95%E7%94%A8fixture/Pasted-20240924-2_hu_9191835c894c17a3.webp"
width="1024"
height="343"
srcset="https://chengxiaqiucao.github.io/post/017-pytest%E4%B8%AD%E8%87%AA%E5%8A%A8%E6%8C%87%E5%AE%9A%E5%8F%AF%E5%BC%95%E7%94%A8fixture/Pasted-20240924-2_hu_d451c60ffee539ac.webp 480w, https://chengxiaqiucao.github.io/post/017-pytest%E4%B8%AD%E8%87%AA%E5%8A%A8%E6%8C%87%E5%AE%9A%E5%8F%AF%E5%BC%95%E7%94%A8fixture/Pasted-20240924-2_hu_9191835c894c17a3.webp 1024w"
loading="lazy"
class="gallery-image"
data-flex-grow="298"
data-flex-basis="717px"
>
&lt;/p>
&lt;p>The above~~&lt;/p></description></item><item><title>Creating a Product Demo with SeleniumBase</title><link>https://chengxiaqiucao.github.io/en/post/019-%E7%94%A8seleniumbase%E5%88%B6%E4%BD%9C%E4%BA%A7%E5%93%81demo/</link><pubDate>Mon, 23 Sep 2024 00:00:00 +0000</pubDate><guid>https://chengxiaqiucao.github.io/en/post/019-%E7%94%A8seleniumbase%E5%88%B6%E4%BD%9C%E4%BA%A7%E5%93%81demo/</guid><description>&lt;img src="https://chengxiaqiucao.github.io/post/019-%E7%94%A8seleniumbase%E5%88%B6%E4%BD%9C%E4%BA%A7%E5%93%81demo/seleniumBase.webp" alt="Featured image of post Creating a Product Demo with SeleniumBase" />&lt;p>Selenium, as the most popular open-source web Test Automation framework today, has been developed for 20 years. It is powerful, and its webdriver protocol has also become a de facto standard in the field of Test Automation. Based on the Selenium framework, many extension frameworks built on top of it have emerged. One example is SeleniumBase, which we introduce in this article.&lt;/p>
&lt;h2 id="what-is-seleniumbase">What Is SeleniumBase?
&lt;/h2>&lt;p>SeleniumBase is a Python library built on top of the Selenium framework that further enhances scripting.
On top of Selenium&amp;rsquo;s original functionality, it simplifies the way automation scripts are written and invoked, and it is deeply integrated with the &lt;code>pytest&lt;/code> framework. Most importantly, it provides a variety of different script modes, including script recording, slowed-down execution, in-run debugging, and the demo feature we are going to introduce in this article.&lt;/p>
&lt;p>Although SeleniumBase is very powerful, the underlying implementation logic of the automation still follows the main characteristics of Selenium. So here we will not specifically introduce SeleniumBase&amp;rsquo;s wrappers for writing automation scripts. But one excellent thing about this library is that, through JS injection, it makes the automation running process more intuitive and easier to demonstrate.&lt;/p>
&lt;p>For example, the demo creation we will see below.&lt;/p>
&lt;h2 id="advantages-of-completing-a-demo-through-automation-scripts">Advantages of Completing a Demo Through Automation Scripts
&lt;/h2>&lt;p>As test engineers, especially with the popularity of agile development nowadays, the end of an iteration usually includes an iteration review and demo session. And as test engineers, a lot of the feature demos within iterations are done by us.&lt;/p>
&lt;p>This also includes the fact that, when introducing product features to customers or leaders, explaining the features through actual product operations is essential as well.&lt;/p>
&lt;p>But in practice, if we can display in advance the key points that need to be explained while the automated test is executing, the effect is very good, and it can also avoid some accidental misoperations on the spot.&lt;/p>
&lt;p>So this feature of SeleniumBase can really play to its strengths here.&lt;/p>
&lt;h2 id="the-process-of-creating-a-product-demo-with-seleniumbase">The Process of Creating a Product Demo with SeleniumBase
&lt;/h2>&lt;p>First, take a look at a demo of the open-source update information on my blog site, completed with SeleniumBase&lt;/p>
&lt;p>&lt;img src="https://chengxiaqiucao.github.io/post/019-%E7%94%A8seleniumbase%E5%88%B6%E4%BD%9C%E4%BA%A7%E5%93%81demo/demo.gif"
width="1677"
height="968"
loading="lazy"
class="gallery-image"
data-flex-grow="173"
data-flex-basis="415px"
>
&lt;/p>
&lt;p>In fact, its principle is fairly simple: through its wrapped &lt;code>BaseCase&lt;/code> class, while the corresponding operation steps are being executed, it injects pre-packaged JS to highlight the elements being operated on and give some guidance hints.&lt;/p>
&lt;p>The corresponding &lt;code>create_introjs_tour()&lt;/code> method in the base class creates the demo tour. It also offers different JS theme choices here, which is very powerful.&lt;/p>
&lt;p>Then &lt;code>add_tour_step()&lt;/code> adds the steps, and &lt;code>play_tour() &lt;/code> executes the steps.&lt;/p>
&lt;p>The corresponding demo generation code:&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;span class="lnt">12
&lt;/span>&lt;span class="lnt">13
&lt;/span>&lt;span class="lnt">14
&lt;/span>&lt;span class="lnt">15
&lt;/span>&lt;span class="lnt">16
&lt;/span>&lt;span class="lnt">17
&lt;/span>&lt;span class="lnt">18
&lt;/span>&lt;span class="lnt">19
&lt;/span>&lt;span class="lnt">20
&lt;/span>&lt;span class="lnt">21
&lt;/span>&lt;span class="lnt">22
&lt;/span>&lt;span class="lnt">23
&lt;/span>&lt;span class="lnt">24
&lt;/span>&lt;span class="lnt">25
&lt;/span>&lt;span class="lnt">26
&lt;/span>&lt;span class="lnt">27
&lt;/span>&lt;span class="lnt">28
&lt;/span>&lt;span class="lnt">29
&lt;/span>&lt;span class="lnt">30
&lt;/span>&lt;span class="lnt">31
&lt;/span>&lt;span class="lnt">32
&lt;/span>&lt;span class="lnt">33
&lt;/span>&lt;span class="lnt">34
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-python" data-lang="python">&lt;span class="line">&lt;span class="cl">&lt;span class="kn">from&lt;/span> &lt;span class="nn">seleniumbase&lt;/span> &lt;span class="kn">import&lt;/span> &lt;span class="n">BaseCase&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">BaseCase&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">main&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="vm">__name__&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="vm">__file__&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="k">class&lt;/span> &lt;span class="nc">MyTourClass&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">BaseCase&lt;/span>&lt;span class="p">):&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">def&lt;/span> &lt;span class="nf">test_blog_tour&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="bp">self&lt;/span>&lt;span class="p">):&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="bp">self&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">open&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s2">&amp;#34;https://chengxiaqiucao.github.io/&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="bp">self&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">wait_for_element&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s1">&amp;#39;[class=&amp;#34;site-logo&amp;#34;]&amp;#39;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="bp">self&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">set_introjs_colors&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s2">&amp;#34;#f34565&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="s2">&amp;#34;#c55409&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="bp">self&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">create_introjs_tour&lt;/span>&lt;span class="p">()&lt;/span> &lt;span class="c1">#&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="bp">self&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">add_tour_step&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s2">&amp;#34;Selenium Base制作Demo演示&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">title&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s2">&amp;#34;城下秋草的Demo&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="bp">self&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">add_tour_step&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s2">&amp;#34;查看热门开源项目&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="s1">&amp;#39;#main-menu &amp;gt; li:nth-child(6) &amp;gt; a&amp;#39;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="bp">self&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">play_tour&lt;/span>&lt;span class="p">()&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="bp">self&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">highlight_click&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s1">&amp;#39;#main-menu &amp;gt; li:nth-child(6) &amp;gt; a&amp;#39;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="bp">self&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">wait_for_element&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s1">&amp;#39;[class=&amp;#34;article-title&amp;#34;]&amp;#39;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="bp">self&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">create_introjs_tour&lt;/span>&lt;span class="p">()&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="bp">self&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">add_tour_step&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s2">&amp;#34;选择Selenium项目查看&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="s1">&amp;#39;#seleniumpageselenium-10 &amp;gt; a&amp;#39;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="bp">self&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">play_tour&lt;/span>&lt;span class="p">()&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="bp">self&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">highlight_click&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s1">&amp;#39;#seleniumpageselenium-10 &amp;gt; a&amp;#39;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="bp">self&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">ad_block&lt;/span>&lt;span class="p">()&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="bp">self&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">wait_for_element&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s1">&amp;#39;[class=&amp;#34;section-title&amp;#34;]&amp;#39;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="bp">self&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">create_introjs_tour&lt;/span>&lt;span class="p">()&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="bp">self&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">add_tour_step&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s2">&amp;#34;返回主页&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="s1">&amp;#39;[class=&amp;#34;site-logo&amp;#34;]&amp;#39;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="bp">self&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">play_tour&lt;/span>&lt;span class="p">()&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="bp">self&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">highlight_click&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s1">&amp;#39;[class=&amp;#34;site-logo&amp;#34;]&amp;#39;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="bp">self&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">wait_for_element&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s1">&amp;#39;[title=&amp;#34;搜索&amp;#34;]&amp;#39;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="bp">self&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">create_introjs_tour&lt;/span>&lt;span class="p">()&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="bp">self&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">add_tour_step&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s2">&amp;#34;3秒停顿后继续...&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="bp">self&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">add_tour_step&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s2">&amp;#34;开始下一个演示:&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="bp">self&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">play_tour&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">interval&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="mi">3&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>As for the JS injected in the actual demo, we can also export the corresponding JS script through the &lt;code>self.export_tour&lt;/code> statement, so that it can be used directly later.&lt;/p>
&lt;p>Similarly, there is also its Demo mode, which is actually quite similar to the guided tour mode, except that it more often automatically slows down and highlights the automation execution steps to emphasize the verification points.&lt;/p>
&lt;p>The above is my sharing on this cool feature of the SeleniumBase library~&lt;/p></description></item><item><title>Projects Suitable for Practicing Test Automation</title><link>https://chengxiaqiucao.github.io/en/post/012-%E8%87%AA%E5%8A%A8%E5%8C%96%E6%B5%8B%E8%AF%95%E7%BB%83%E6%89%8B%E9%A1%B9%E7%9B%AE%E6%94%B6%E9%9B%86/</link><pubDate>Fri, 20 Sep 2024 15:24:19 +0800</pubDate><guid>https://chengxiaqiucao.github.io/en/post/012-%E8%87%AA%E5%8A%A8%E5%8C%96%E6%B5%8B%E8%AF%95%E7%BB%83%E6%89%8B%E9%A1%B9%E7%9B%AE%E6%94%B6%E9%9B%86/</guid><description>&lt;img src="https://chengxiaqiucao.github.io/post/012-%E8%87%AA%E5%8A%A8%E5%8C%96%E6%B5%8B%E8%AF%95%E7%BB%83%E6%89%8B%E9%A1%B9%E7%9B%AE%E6%94%B6%E9%9B%86/autotest.webp" alt="Featured image of post Projects Suitable for Practicing Test Automation" />&lt;p>Many friends who are new to test automation have read a lot of tutorials, but are troubled by not having suitable projects to practice with. Here the author would like to share some good practice projects that have been collected.&lt;/p>
&lt;h2 id="demoqa">DemoQA
&lt;/h2>&lt;p>&lt;a class="link" href="https://demoqa.com/" target="_blank" rel="noopener"
>DemoQA&lt;/a> is a practice website specifically designed for practicing web test automation such as Selenium.
&lt;img src="https://chengxiaqiucao.github.io/post/012-%E8%87%AA%E5%8A%A8%E5%8C%96%E6%B5%8B%E8%AF%95%E7%BB%83%E6%89%8B%E9%A1%B9%E7%9B%AE%E6%94%B6%E9%9B%86/Pasted-20240920-1_hu_caad5f561bf5254e.webp"
width="1024"
height="799"
srcset="https://chengxiaqiucao.github.io/post/012-%E8%87%AA%E5%8A%A8%E5%8C%96%E6%B5%8B%E8%AF%95%E7%BB%83%E6%89%8B%E9%A1%B9%E7%9B%AE%E6%94%B6%E9%9B%86/Pasted-20240920-1_hu_91a4beea3472770e.webp 480w, https://chengxiaqiucao.github.io/post/012-%E8%87%AA%E5%8A%A8%E5%8C%96%E6%B5%8B%E8%AF%95%E7%BB%83%E6%89%8B%E9%A1%B9%E7%9B%AE%E6%94%B6%E9%9B%86/Pasted-20240920-1_hu_caad5f561bf5254e.webp 1024w"
loading="lazy"
class="gallery-image"
data-flex-grow="128"
data-flex-basis="307px"
>
It covers all kinds of commonly used elements and controls in the process of learning Web automation, allowing a fairly comprehensive study of page handling.
&lt;img src="https://chengxiaqiucao.github.io/post/012-%E8%87%AA%E5%8A%A8%E5%8C%96%E6%B5%8B%E8%AF%95%E7%BB%83%E6%89%8B%E9%A1%B9%E7%9B%AE%E6%94%B6%E9%9B%86/Pasted-20240920-2_hu_b7d8e167c37cf614.webp"
width="1024"
height="1030"
srcset="https://chengxiaqiucao.github.io/post/012-%E8%87%AA%E5%8A%A8%E5%8C%96%E6%B5%8B%E8%AF%95%E7%BB%83%E6%89%8B%E9%A1%B9%E7%9B%AE%E6%94%B6%E9%9B%86/Pasted-20240920-2_hu_390ddd66ed6774bf.webp 480w, https://chengxiaqiucao.github.io/post/012-%E8%87%AA%E5%8A%A8%E5%8C%96%E6%B5%8B%E8%AF%95%E7%BB%83%E6%89%8B%E9%A1%B9%E7%9B%AE%E6%94%B6%E9%9B%86/Pasted-20240920-2_hu_b7d8e167c37cf614.webp 1024w"
loading="lazy"
class="gallery-image"
data-flex-grow="99"
data-flex-basis="238px"
>
&lt;/p>
&lt;h2 id="the-internet">The-internet
&lt;/h2>&lt;p>&lt;a class="link" href="https://the-internet.herokuapp.com/" target="_blank" rel="noopener"
>The-Internet&lt;/a> is also a project aimed at beginners, specifically for test automation practice, and is quite similar to DemoQA. The scenarios can complement each other. Besides using it online, you can also download the source code from its GitHub project and deploy it yourself (based on Ruby).&lt;/p>
&lt;p>&lt;img src="https://chengxiaqiucao.github.io/post/012-%E8%87%AA%E5%8A%A8%E5%8C%96%E6%B5%8B%E8%AF%95%E7%BB%83%E6%89%8B%E9%A1%B9%E7%9B%AE%E6%94%B6%E9%9B%86/Pasted-20240920-3_hu_89a7c7b01e251835.webp"
width="1024"
height="872"
srcset="https://chengxiaqiucao.github.io/post/012-%E8%87%AA%E5%8A%A8%E5%8C%96%E6%B5%8B%E8%AF%95%E7%BB%83%E6%89%8B%E9%A1%B9%E7%9B%AE%E6%94%B6%E9%9B%86/Pasted-20240920-3_hu_a4722a5cb8eba8a2.webp 480w, https://chengxiaqiucao.github.io/post/012-%E8%87%AA%E5%8A%A8%E5%8C%96%E6%B5%8B%E8%AF%95%E7%BB%83%E6%89%8B%E9%A1%B9%E7%9B%AE%E6%94%B6%E9%9B%86/Pasted-20240920-3_hu_89a7c7b01e251835.webp 1024w"
loading="lazy"
class="gallery-image"
data-flex-grow="117"
data-flex-basis="281px"
>
&lt;/p>
&lt;h2 id="saucelab-app">SauceLab App
&lt;/h2>&lt;p>SauceLab is a testing service provider, and &lt;a class="link" href="https://www.saucedemo.com/" target="_blank" rel="noopener"
>SauceDemo&lt;/a> is a site it provides for test automation practice.&lt;/p>
&lt;p>&lt;img src="https://chengxiaqiucao.github.io/post/012-%E8%87%AA%E5%8A%A8%E5%8C%96%E6%B5%8B%E8%AF%95%E7%BB%83%E6%89%8B%E9%A1%B9%E7%9B%AE%E6%94%B6%E9%9B%86/Pasted-20240920-4_hu_fdbbdecf3fb01f7c.webp"
width="1024"
height="553"
srcset="https://chengxiaqiucao.github.io/post/012-%E8%87%AA%E5%8A%A8%E5%8C%96%E6%B5%8B%E8%AF%95%E7%BB%83%E6%89%8B%E9%A1%B9%E7%9B%AE%E6%94%B6%E9%9B%86/Pasted-20240920-4_hu_2c695ebfd002b501.webp 480w, https://chengxiaqiucao.github.io/post/012-%E8%87%AA%E5%8A%A8%E5%8C%96%E6%B5%8B%E8%AF%95%E7%BB%83%E6%89%8B%E9%A1%B9%E7%9B%AE%E6%94%B6%E9%9B%86/Pasted-20240920-4_hu_fdbbdecf3fb01f7c.webp 1024w"
loading="lazy"
class="gallery-image"
data-flex-grow="185"
data-flex-basis="444px"
>
&lt;/p>
&lt;p>In addition to the Web version, this project also provides a mobile version, my-demo-app, which can be used for practicing Android/IOS application test automation, and can be obtained through SauceLab&amp;rsquo;s GitHub project.&lt;/p>
&lt;p>&lt;a class="link" href="https://github.com/saucelabs/my-demo-app-android" target="_blank" rel="noopener"
>https://github.com/saucelabs/my-demo-app-android&lt;/a>&lt;/p>
&lt;p>&lt;a class="link" href="https://github.com/saucelabs/my-demo-app-ios" target="_blank" rel="noopener"
>https://github.com/saucelabs/my-demo-app-ios&lt;/a>&lt;/p>
&lt;p>&lt;img src="https://chengxiaqiucao.github.io/post/012-%E8%87%AA%E5%8A%A8%E5%8C%96%E6%B5%8B%E8%AF%95%E7%BB%83%E6%89%8B%E9%A1%B9%E7%9B%AE%E6%94%B6%E9%9B%86/Pasted-20240920-5_hu_efabd0c695eac201.webp"
width="1024"
height="1771"
srcset="https://chengxiaqiucao.github.io/post/012-%E8%87%AA%E5%8A%A8%E5%8C%96%E6%B5%8B%E8%AF%95%E7%BB%83%E6%89%8B%E9%A1%B9%E7%9B%AE%E6%94%B6%E9%9B%86/Pasted-20240920-5_hu_cfa917dabb555c6b.webp 480w, https://chengxiaqiucao.github.io/post/012-%E8%87%AA%E5%8A%A8%E5%8C%96%E6%B5%8B%E8%AF%95%E7%BB%83%E6%89%8B%E9%A1%B9%E7%9B%AE%E6%94%B6%E9%9B%86/Pasted-20240920-5_hu_efabd0c695eac201.webp 1024w"
loading="lazy"
class="gallery-image"
data-flex-grow="57"
data-flex-basis="138px"
>
&lt;/p>
&lt;h2 id="sahi-test">Sahi Test
&lt;/h2>&lt;p>&lt;a class="link" href="https://sahitest.com/demo/" target="_blank" rel="noopener"
>Sahi Test&lt;/a> is a project self-built by a testing blogger for test automation practice, containing very rich scenarios.&lt;/p>
&lt;p>&lt;img src="https://chengxiaqiucao.github.io/post/012-%E8%87%AA%E5%8A%A8%E5%8C%96%E6%B5%8B%E8%AF%95%E7%BB%83%E6%89%8B%E9%A1%B9%E7%9B%AE%E6%94%B6%E9%9B%86/Pasted-20240920-6_hu_34f195d304b616d5.webp"
width="1024"
height="475"
srcset="https://chengxiaqiucao.github.io/post/012-%E8%87%AA%E5%8A%A8%E5%8C%96%E6%B5%8B%E8%AF%95%E7%BB%83%E6%89%8B%E9%A1%B9%E7%9B%AE%E6%94%B6%E9%9B%86/Pasted-20240920-6_hu_6959b9a5fcd1087c.webp 480w, https://chengxiaqiucao.github.io/post/012-%E8%87%AA%E5%8A%A8%E5%8C%96%E6%B5%8B%E8%AF%95%E7%BB%83%E6%89%8B%E9%A1%B9%E7%9B%AE%E6%94%B6%E9%9B%86/Pasted-20240920-6_hu_34f195d304b616d5.webp 1024w"
loading="lazy"
class="gallery-image"
data-flex-grow="215"
data-flex-basis="516px"
>
&lt;/p>
&lt;h2 id="guru99-demo">GURU99 Demo
&lt;/h2>&lt;p>&lt;a class="link" href="https://demo.guru99.com/" target="_blank" rel="noopener"
>Demo Guru99&lt;/a> is a collection of multiple projects integrated by the Guru99 website for test automation practice, including insurance, banking, telecommunications, and the Tour project that comes with the traditional test automation tool QTP.&lt;/p>
&lt;p>&lt;img src="https://chengxiaqiucao.github.io/post/012-%E8%87%AA%E5%8A%A8%E5%8C%96%E6%B5%8B%E8%AF%95%E7%BB%83%E6%89%8B%E9%A1%B9%E7%9B%AE%E6%94%B6%E9%9B%86/Pasted-20240920-7_hu_14fb7398b0585736.webp"
width="1024"
height="584"
srcset="https://chengxiaqiucao.github.io/post/012-%E8%87%AA%E5%8A%A8%E5%8C%96%E6%B5%8B%E8%AF%95%E7%BB%83%E6%89%8B%E9%A1%B9%E7%9B%AE%E6%94%B6%E9%9B%86/Pasted-20240920-7_hu_cf7f098d6792537c.webp 480w, https://chengxiaqiucao.github.io/post/012-%E8%87%AA%E5%8A%A8%E5%8C%96%E6%B5%8B%E8%AF%95%E7%BB%83%E6%89%8B%E9%A1%B9%E7%9B%AE%E6%94%B6%E9%9B%86/Pasted-20240920-7_hu_14fb7398b0585736.webp 1024w"
loading="lazy"
class="gallery-image"
data-flex-grow="175"
data-flex-basis="421px"
>
&lt;img src="https://chengxiaqiucao.github.io/post/012-%E8%87%AA%E5%8A%A8%E5%8C%96%E6%B5%8B%E8%AF%95%E7%BB%83%E6%89%8B%E9%A1%B9%E7%9B%AE%E6%94%B6%E9%9B%86/Pasted-20240920-8_hu_7de8ebbdfc048061.webp"
width="1024"
height="1228"
srcset="https://chengxiaqiucao.github.io/post/012-%E8%87%AA%E5%8A%A8%E5%8C%96%E6%B5%8B%E8%AF%95%E7%BB%83%E6%89%8B%E9%A1%B9%E7%9B%AE%E6%94%B6%E9%9B%86/Pasted-20240920-8_hu_2e29f51de3b2f64f.webp 480w, https://chengxiaqiucao.github.io/post/012-%E8%87%AA%E5%8A%A8%E5%8C%96%E6%B5%8B%E8%AF%95%E7%BB%83%E6%89%8B%E9%A1%B9%E7%9B%AE%E6%94%B6%E9%9B%86/Pasted-20240920-8_hu_7de8ebbdfc048061.webp 1024w"
loading="lazy"
class="gallery-image"
data-flex-grow="83"
data-flex-basis="200px"
>
&lt;/p>
&lt;h2 id="jpetstore">JpetStore
&lt;/h2>&lt;p>&lt;strong>JpetStore&lt;/strong> is a pet store application provided by mybatis. Project address: &lt;a class="link" href="https://github.com/mybatis/jpetstore-6" target="_blank" rel="noopener"
>https://github.com/mybatis/jpetstore-6&lt;/a>&lt;/p>
&lt;p>&lt;img src="https://chengxiaqiucao.github.io/post/012-%E8%87%AA%E5%8A%A8%E5%8C%96%E6%B5%8B%E8%AF%95%E7%BB%83%E6%89%8B%E9%A1%B9%E7%9B%AE%E6%94%B6%E9%9B%86/Pasted-20240920-10_hu_21d4a853d8d7fb95.webp"
width="1024"
height="408"
srcset="https://chengxiaqiucao.github.io/post/012-%E8%87%AA%E5%8A%A8%E5%8C%96%E6%B5%8B%E8%AF%95%E7%BB%83%E6%89%8B%E9%A1%B9%E7%9B%AE%E6%94%B6%E9%9B%86/Pasted-20240920-10_hu_cd508f2c7087ad8a.webp 480w, https://chengxiaqiucao.github.io/post/012-%E8%87%AA%E5%8A%A8%E5%8C%96%E6%B5%8B%E8%AF%95%E7%BB%83%E6%89%8B%E9%A1%B9%E7%9B%AE%E6%94%B6%E9%9B%86/Pasted-20240920-10_hu_21d4a853d8d7fb95.webp 1024w"
loading="lazy"
class="gallery-image"
data-flex-grow="251"
data-flex-basis="602px"
>
&lt;/p>
&lt;h2 id="opencart">OpenCart
&lt;/h2>&lt;p>Besides the projects above that are specifically provided for test automation practice, we can also find some more fully featured open source free sites to use when practicing.&lt;/p>
&lt;p>For example, &lt;a class="link" href="https://demo.opencart.com/" target="_blank" rel="noopener"
>OpenCart&lt;/a> is an open source e-commerce website, and you can practice based on its Demo site.&lt;/p>
&lt;p>&lt;img src="https://chengxiaqiucao.github.io/post/012-%E8%87%AA%E5%8A%A8%E5%8C%96%E6%B5%8B%E8%AF%95%E7%BB%83%E6%89%8B%E9%A1%B9%E7%9B%AE%E6%94%B6%E9%9B%86/Pasted-20240920_hu_70c9b908eda30838.webp"
width="1024"
height="786"
srcset="https://chengxiaqiucao.github.io/post/012-%E8%87%AA%E5%8A%A8%E5%8C%96%E6%B5%8B%E8%AF%95%E7%BB%83%E6%89%8B%E9%A1%B9%E7%9B%AE%E6%94%B6%E9%9B%86/Pasted-20240920_hu_bcdfb8e711be5443.webp 480w, https://chengxiaqiucao.github.io/post/012-%E8%87%AA%E5%8A%A8%E5%8C%96%E6%B5%8B%E8%AF%95%E7%BB%83%E6%89%8B%E9%A1%B9%E7%9B%AE%E6%94%B6%E9%9B%86/Pasted-20240920_hu_70c9b908eda30838.webp 1024w"
loading="lazy"
class="gallery-image"
data-flex-grow="130"
data-flex-basis="312px"
>
&lt;/p>
&lt;h2 id="orangehrm">OrangeHRM
&lt;/h2>&lt;p>&lt;a class="link" href="https://opensource-demo.orangehrmlive.com/web/index.php/auth/login" target="_blank" rel="noopener"
>OrangeHRM&lt;/a> is a powerful open source HR management system, and it is likewise a very good choice as a practice site for test automation.&lt;/p>
&lt;p>&lt;img src="https://chengxiaqiucao.github.io/post/012-%E8%87%AA%E5%8A%A8%E5%8C%96%E6%B5%8B%E8%AF%95%E7%BB%83%E6%89%8B%E9%A1%B9%E7%9B%AE%E6%94%B6%E9%9B%86/Pasted-20240920-9_hu_c8cdca1f4ed49373.webp"
width="1024"
height="550"
srcset="https://chengxiaqiucao.github.io/post/012-%E8%87%AA%E5%8A%A8%E5%8C%96%E6%B5%8B%E8%AF%95%E7%BB%83%E6%89%8B%E9%A1%B9%E7%9B%AE%E6%94%B6%E9%9B%86/Pasted-20240920-9_hu_f357860bafb0eb1c.webp 480w, https://chengxiaqiucao.github.io/post/012-%E8%87%AA%E5%8A%A8%E5%8C%96%E6%B5%8B%E8%AF%95%E7%BB%83%E6%89%8B%E9%A1%B9%E7%9B%AE%E6%94%B6%E9%9B%86/Pasted-20240920-9_hu_c8cdca1f4ed49373.webp 1024w"
loading="lazy"
class="gallery-image"
data-flex-grow="186"
data-flex-basis="447px"
>
&lt;/p>
&lt;p>The above are some commonly used websites collected and organized by the author that can be used for test automation practice. Of course, there are in fact a large number of fairly mature web applications on open source sites, and we can absolutely set them up locally before practicing. If you have any other good practice projects to recommend, feel free to add them in the comments~~&lt;/p></description></item><item><title>Detailed Guide to Using Selenium Manager</title><link>https://chengxiaqiucao.github.io/en/post/013-selenium-manager/</link><pubDate>Sat, 07 Sep 2024 18:03:04 +0800</pubDate><guid>https://chengxiaqiucao.github.io/en/post/013-selenium-manager/</guid><description>&lt;img src="https://chengxiaqiucao.github.io/post/013-selenium-manager/Se-m.webp" alt="Featured image of post Detailed Guide to Using Selenium Manager" />&lt;p>Selenium was born in 2004. With its open source nature and comprehensive features, it has long ranked Top1 in the field of Web test automation tools, and is currently the most mainstream Web test automation tool. Moreover, Selenium&amp;rsquo;s core Webdriver serves as the prevailing W3C standard and is widely referenced by various tools. It can be said to be the de facto standard for web test automation today.&lt;/p>
&lt;h2 id="changes-brought-by-selenium-4">Changes Brought by Selenium 4
&lt;/h2>&lt;p>After years of evolution, Selenium itself has now been released up to version V4.24. Although usages and materials related to the V3 version are still widely circulated online, Selenium 4 is actually a very major update. Several of its core components have undergone extensive refactoring.&lt;/p>
&lt;ul>
&lt;li>WebDriver switched from the original Json Wire Protocol to the W3C standard definition&lt;/li>
&lt;li>Selenium IDE completed its refactoring and feature optimization&lt;/li>
&lt;li>Selenium Grid completed its refactoring and supports a more flexible cloud service architecture&lt;/li>
&lt;/ul>
&lt;p>In addition, Selenium 4 introduced a very important tool, which is the Selenium Manager we are going to focus on in this article (it was actually introduced only in V4.6, and its features were basically complete only by V4.12&lt;/p>
&lt;h2 id="problems-caused-by-the-original-browser-driver-approach">Problems Caused by the Original Browser Driver Approach
&lt;/h2>&lt;p>To understand Selenium Manager, we still need to first understand how Selenium works.&lt;/p>
&lt;h3 id="how-selenium-works">How Selenium Works
&lt;/h3>&lt;p>The figure below is the basic architecture of Selenium&amp;rsquo;s local execution given on the official site.
&lt;img src="https://chengxiaqiucao.github.io/post/013-selenium-manager/Pasted-20240908_hu_f870e32cb444c893.webp"
width="1024"
height="487"
srcset="https://chengxiaqiucao.github.io/post/013-selenium-manager/Pasted-20240908_hu_4a26b59caeb4920d.webp 480w, https://chengxiaqiucao.github.io/post/013-selenium-manager/Pasted-20240908_hu_f870e32cb444c893.webp 1024w"
loading="lazy"
alt="How Selenium Works"
class="gallery-image"
data-flex-grow="210"
data-flex-basis="504px"
>
&lt;/p>
&lt;p>As can be seen, Selenium actually accomplishes automation by driving different types of browsers (Chrome, Firefox, IE, Edge, Safari, etc.) through the webdriver protocol to complete specified actions, thereby achieving the goal of automated execution.&lt;/p>
&lt;p>The key to driving a browser is the browser Driver that corresponds to the browser, such as ChromeDriver for Chrome, GecoDriver for FireFox, and so on.&lt;/p>
&lt;p>And Selenium itself interacts with the browser Driver based on the WebDriver protocol.&lt;/p>
&lt;h3 id="the-problems-it-causes">The Problems It Causes
&lt;/h3>&lt;p>Although this architecture and working principle are clear, there is one problem: browser versions are constantly being updated. And &lt;strong>the browser driver version needs to match the browser version&lt;/strong>; when mismatched driver and browser versions work together, various unexpected exceptions may occur. Therefore, for Selenium to work properly, before writing code with the Selenium library, the first thing is to ensure the deployment and matching of the browser driver and browser versions.&lt;/p>
&lt;p>But browser versions and their corresponding drivers are usually maintained by the browser vendors.&lt;/p>
&lt;p>So preparing the test automation environment here becomes rather complicated: you need to install the browser of the corresponding version under test, and at the same time find the driver corresponding to that version, then configure the relevant paths for Selenium, and only then can Selenium complete normal driving.&lt;/p>
&lt;p>In addition, browser versions generally also have an &lt;strong>auto-update feature&lt;/strong>. It may happen that, without the user noticing, the version has already changed, but at that time the driver version is not updated synchronously, so this also &lt;strong>leads to the potential problem of driver and browser version mismatch&lt;/strong>.&lt;/p>
&lt;p>This problem was actually not well resolved for a long time. With Selenium 3 and the early versions of Selenium 4, when we deployed a Selenium automation environment, obtaining and matching browser versions and driver versions was always a rather troublesome task, and because of this it discouraged quite a few test automation beginners.&lt;/p>
&lt;h3 id="chromes-response-to-the-driver-problem">Chrome&amp;rsquo;s Response to the Driver Problem
&lt;/h3>&lt;p>Since this problem has existed for a long time, browser vendors have also actually realized the troubles that a mismatch between driver and browser versions brings to test automation.&lt;/p>
&lt;p>Taking Chrome as an example, if we go to the &lt;a class="link" href="https://developer.chrome.com/docs/chromedriver/downloads" target="_blank" rel="noopener"
>official ChromeDriver downloads&lt;/a> page, we will see a page like this&lt;/p>
&lt;p>&lt;img src="https://chengxiaqiucao.github.io/post/013-selenium-manager/Pasted-20240910_hu_8c1b369a2db3be19.webp"
width="1024"
height="616"
srcset="https://chengxiaqiucao.github.io/post/013-selenium-manager/Pasted-20240910_hu_a142dc0f9404e599.webp 480w, https://chengxiaqiucao.github.io/post/013-selenium-manager/Pasted-20240910_hu_8c1b369a2db3be19.webp 1024w"
loading="lazy"
class="gallery-image"
data-flex-grow="166"
data-flex-basis="399px"
>
&lt;/p>
&lt;p>As can be seen, Chrome Driver downloads here are only provided up to version 114, while the latest Chrome has actually already reached version 128.
For versions after 115, the Chrome browser actually adjusted the driver release strategy, that is, Chrome driver is released in sync with the Chrome for Testing version, strictly ensuring the synchronous matching of driver and browser versions.&lt;/p>
&lt;p>So why is there a Chrome for Testing version here?&lt;/p>
&lt;p>&lt;img src="https://chengxiaqiucao.github.io/post/013-selenium-manager/Pasted-20240910-1_hu_dc3c40439e010326.webp"
width="1024"
height="815"
srcset="https://chengxiaqiucao.github.io/post/013-selenium-manager/Pasted-20240910-1_hu_e5c6c453afd4095b.webp 480w, https://chengxiaqiucao.github.io/post/013-selenium-manager/Pasted-20240910-1_hu_dc3c40439e010326.webp 1024w"
loading="lazy"
class="gallery-image"
data-flex-grow="125"
data-flex-basis="301px"
>
As we mentioned earlier, browser versions have auto-update; if an auto-update happens, the driver version is not updated synchronously, thus causing a mismatch between driver and browser.&lt;/p>
&lt;p>So the main difference between Chrome for Testing and the official version is actually that &lt;strong>the for Testing version does not perform auto-updates&lt;/strong>.&lt;/p>
&lt;p>In this way, together with the sharing of version numbers with the browser version, it is very convenient to ensure consistency between the browser and the driver.&lt;/p>
&lt;h3 id="seleniums-solution-to-the-driver-matching-problem">Selenium&amp;rsquo;s Solution to the Driver Matching Problem
&lt;/h3>&lt;p>The above is the solution given by browsers to the driver matching problem, but it still does not completely solve the problem that the browser and Driver need to be obtained and specified separately. So Selenium&amp;rsquo;s official solution to this problem is Selenium Manager. It is actually an executable program included in the Selenium library, requiring no additional installation.&lt;/p>
&lt;p>&lt;img src="https://chengxiaqiucao.github.io/post/013-selenium-manager/Pasted-20240910-2_hu_c480db756ac6f493.webp"
width="1024"
height="1233"
srcset="https://chengxiaqiucao.github.io/post/013-selenium-manager/Pasted-20240910-2_hu_8b29d423e5a75c8a.webp 480w, https://chengxiaqiucao.github.io/post/013-selenium-manager/Pasted-20240910-2_hu_c480db756ac6f493.webp 1024w"
loading="lazy"
class="gallery-image"
data-flex-grow="83"
data-flex-basis="199px"
>
&lt;/p>
&lt;p>If we currently use Selenium V4 to execute a simple test automation script:&lt;/p>
&lt;p>For example, to search for the Chinese phrase &lt;code>城下秋草 测试&lt;/code> on Baidu, the code is as follows:&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;span class="lnt">12
&lt;/span>&lt;span class="lnt">13
&lt;/span>&lt;span class="lnt">14
&lt;/span>&lt;span class="lnt">15
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-python" data-lang="python">&lt;span class="line">&lt;span class="cl">&lt;span class="kn">from&lt;/span> &lt;span class="nn">selenium&lt;/span> &lt;span class="kn">import&lt;/span> &lt;span class="n">webdriver&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="kn">from&lt;/span> &lt;span class="nn">selenium.webdriver.common.by&lt;/span> &lt;span class="kn">import&lt;/span> &lt;span class="n">By&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="kn">from&lt;/span> &lt;span class="nn">time&lt;/span> &lt;span class="kn">import&lt;/span> &lt;span class="n">sleep&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="k">def&lt;/span> &lt;span class="nf">test_baidu_search&lt;/span>&lt;span class="p">():&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">option&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">webdriver&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">ChromeOptions&lt;/span>&lt;span class="p">()&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">option&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">browser_version&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="s1">&amp;#39;117&amp;#39;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">driver&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">webdriver&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">Chrome&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">options&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="n">option&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">driver&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">get&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s2">&amp;#34;https://www.baidu.com&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">driver&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">find_element&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">By&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">ID&lt;/span>&lt;span class="p">,&lt;/span>&lt;span class="s1">&amp;#39;kw&amp;#39;&lt;/span>&lt;span class="p">)&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">send_keys&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s1">&amp;#39;城下秋草 测试&amp;#39;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">sleep&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="mi">2&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">driver&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">find_element&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">By&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">ID&lt;/span>&lt;span class="p">,&lt;/span>&lt;span class="s1">&amp;#39;su&amp;#39;&lt;/span>&lt;span class="p">)&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">click&lt;/span>&lt;span class="p">()&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">sleep&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="mi">3&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">driver&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">close&lt;/span>&lt;span class="p">()&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>As long as the Selenium library is installed, when executing, it can drive normally, without any special need to obtain the driver and configuration.&lt;/p>
&lt;p>&lt;img src="https://chengxiaqiucao.github.io/post/013-selenium-manager/run.gif"
width="1554"
height="935"
loading="lazy"
class="gallery-image"
data-flex-grow="166"
data-flex-basis="398px"
>
&lt;/p>
&lt;h2 id="source-code-analysis-of-selenium-4-launching-automation-execution">Source Code Analysis of Selenium 4 Launching Automation Execution
&lt;/h2>&lt;p>Here we analyze its startup process from Selenium&amp;rsquo;s Python source code:&lt;/p>
&lt;p>&lt;code>driver = webdriver.Chrome(options=option) &lt;/code>&lt;/p>
&lt;p>This line of code actually calls the webdriver initialization code for the Chromium-based browser in the Selenium library, located at &lt;code>.venv/Lib/site-packages/selenium/webdriver/chromium/webdriver.py&lt;/code>&lt;/p>
&lt;p>During initialization, as can be seen, the DriverFinder method is used to obtain the paths of the browser and the Driver&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;span class="lnt">3
&lt;/span>&lt;span class="lnt">4
&lt;/span>&lt;span class="lnt">5
&lt;/span>&lt;span class="lnt">6
&lt;/span>&lt;span class="lnt">7
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-python" data-lang="python">&lt;span class="line">&lt;span class="cl">&lt;span class="n">finder&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">DriverFinder&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="bp">self&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">service&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">options&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="k">if&lt;/span> &lt;span class="n">finder&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">get_browser_path&lt;/span>&lt;span class="p">():&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">options&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">binary_location&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">finder&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">get_browser_path&lt;/span>&lt;span class="p">()&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">options&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">browser_version&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="kc">None&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="bp">self&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">service&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">path&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">finder&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">get_driver_path&lt;/span>&lt;span class="p">()&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="bp">self&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">service&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">start&lt;/span>&lt;span class="p">()&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>And the method for obtaining the paths actually calls the binary_paths method of the SeleniumManager module&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;span class="lnt">12
&lt;/span>&lt;span class="lnt">13
&lt;/span>&lt;span class="lnt">14
&lt;/span>&lt;span class="lnt">15
&lt;/span>&lt;span class="lnt">16
&lt;/span>&lt;span class="lnt">17
&lt;/span>&lt;span class="lnt">18
&lt;/span>&lt;span class="lnt">19
&lt;/span>&lt;span class="lnt">20
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-python" data-lang="python">&lt;span class="line">&lt;span class="cl">&lt;span class="k">def&lt;/span> &lt;span class="nf">get_browser_path&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="bp">self&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="o">-&amp;gt;&lt;/span> &lt;span class="nb">str&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">return&lt;/span> &lt;span class="bp">self&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">_binary_paths&lt;/span>&lt;span class="p">()[&lt;/span>&lt;span class="s2">&amp;#34;browser_path&amp;#34;&lt;/span>&lt;span class="p">]&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="k">def&lt;/span> &lt;span class="nf">get_driver_path&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="bp">self&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="o">-&amp;gt;&lt;/span> &lt;span class="nb">str&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">return&lt;/span> &lt;span class="bp">self&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">_binary_paths&lt;/span>&lt;span class="p">()[&lt;/span>&lt;span class="s2">&amp;#34;driver_path&amp;#34;&lt;/span>&lt;span class="p">]&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="k">def&lt;/span> &lt;span class="nf">_binary_paths&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="bp">self&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="o">-&amp;gt;&lt;/span> &lt;span class="nb">dict&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">if&lt;/span> &lt;span class="bp">self&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">_paths&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="s2">&amp;#34;driver_path&amp;#34;&lt;/span>&lt;span class="p">]:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">return&lt;/span> &lt;span class="bp">self&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">_paths&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="o">.&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="o">.&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="o">.&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">output&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">SeleniumManager&lt;/span>&lt;span class="p">()&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">binary_paths&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="bp">self&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">_to_args&lt;/span>&lt;span class="p">())&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="o">.&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="o">.&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="o">.&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">return&lt;/span> &lt;span class="bp">self&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">_paths&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>The SeleniumManager module, in turn, executes the SeleniumManager binary program and, based on the relevant parameters, obtains the browser and driver versions.&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;span class="lnt">12
&lt;/span>&lt;span class="lnt">13
&lt;/span>&lt;span class="lnt">14
&lt;/span>&lt;span class="lnt">15
&lt;/span>&lt;span class="lnt">16
&lt;/span>&lt;span class="lnt">17
&lt;/span>&lt;span class="lnt">18
&lt;/span>&lt;span class="lnt">19
&lt;/span>&lt;span class="lnt">20
&lt;/span>&lt;span class="lnt">21
&lt;/span>&lt;span class="lnt">22
&lt;/span>&lt;span class="lnt">23
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-python" data-lang="python">&lt;span class="line">&lt;span class="cl">&lt;span class="k">def&lt;/span> &lt;span class="nf">_run&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">args&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="n">List&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="nb">str&lt;/span>&lt;span class="p">])&lt;/span> &lt;span class="o">-&amp;gt;&lt;/span> &lt;span class="nb">dict&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;&amp;#34;&amp;#34;Executes the Selenium Manager Binary.
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s2">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s2"> :Args: - args: the components of the command being executed. :Returns: The log string containing the driver location. &amp;#34;&amp;#34;&amp;#34;&lt;/span> &lt;span class="n">command&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="s2">&amp;#34; &amp;#34;&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">join&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">args&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">logger&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">debug&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s2">&amp;#34;Executing process: &lt;/span>&lt;span class="si">%s&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">command&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">try&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">if&lt;/span> &lt;span class="n">sys&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">platform&lt;/span> &lt;span class="o">==&lt;/span> &lt;span class="s2">&amp;#34;win32&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">completed_proc&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">subprocess&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">run&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">args&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">capture_output&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="kc">True&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">creationflags&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="n">subprocess&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">CREATE_NO_WINDOW&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">else&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">completed_proc&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">subprocess&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">run&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">args&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">capture_output&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="kc">True&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">stdout&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">completed_proc&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">stdout&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">decode&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s2">&amp;#34;utf-8&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">rstrip&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="se">\n&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">stderr&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">completed_proc&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">stderr&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">decode&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s2">&amp;#34;utf-8&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">rstrip&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="se">\n&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">output&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">json&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">loads&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">stdout&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="k">if&lt;/span> &lt;span class="n">stdout&lt;/span> &lt;span class="o">!=&lt;/span> &lt;span class="s2">&amp;#34;&amp;#34;&lt;/span> &lt;span class="k">else&lt;/span> &lt;span class="p">{&lt;/span>&lt;span class="s2">&amp;#34;logs&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="p">[],&lt;/span> &lt;span class="s2">&amp;#34;result&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="p">{}}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">except&lt;/span> &lt;span class="ne">Exception&lt;/span> &lt;span class="k">as&lt;/span> &lt;span class="n">err&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">raise&lt;/span> &lt;span class="n">WebDriverException&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="sa">f&lt;/span>&lt;span class="s2">&amp;#34;Unsuccessful command executed: &lt;/span>&lt;span class="si">{&lt;/span>&lt;span class="n">command&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="kn">from&lt;/span> &lt;span class="nn">err&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">SeleniumManager&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">_process_logs&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">output&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="s2">&amp;#34;logs&amp;#34;&lt;/span>&lt;span class="p">])&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">result&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">output&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="s2">&amp;#34;result&amp;#34;&lt;/span>&lt;span class="p">]&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">if&lt;/span> &lt;span class="n">completed_proc&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">returncode&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">raise&lt;/span> &lt;span class="n">WebDriverException&lt;/span>&lt;span class="p">(&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="sa">f&lt;/span>&lt;span class="s2">&amp;#34;Unsuccessful command executed: &lt;/span>&lt;span class="si">{&lt;/span>&lt;span class="n">command&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="s2">; code: &lt;/span>&lt;span class="si">{&lt;/span>&lt;span class="n">completed_proc&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">returncode&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="se">\n&lt;/span>&lt;span class="si">{&lt;/span>&lt;span class="n">result&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="se">\n&lt;/span>&lt;span class="si">{&lt;/span>&lt;span class="n">stderr&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">return&lt;/span> &lt;span class="n">result&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>Therefore, when the current Selenium 4 version executes, it uses the SeleniumManager program to determine the required browser and corresponding driver version.&lt;/p>
&lt;h2 id="the-selenium-manager-command-line-program">The Selenium Manager Command-Line Program
&lt;/h2>&lt;p>Through SeleniumManager, based on the browser type and version we configure, it can automatically match the relevant driver version, and connect to the network on its own to obtain the files of the relevant driver and browser version for Selenium to call.
For example, in the case above, we specified the browser version as &lt;code>117&lt;/code>; after execution, the downloaded browser and corresponding driver version are actually saved in the &lt;code>.cache\selenium&lt;/code> directory under the user directory. The figure below shows the driver of version 117 currently updated by the execution.&lt;/p>
&lt;p>&lt;img src="https://chengxiaqiucao.github.io/post/013-selenium-manager/Pasted-20240910-3_hu_233f35873976e072.webp"
width="1024"
height="356"
srcset="https://chengxiaqiucao.github.io/post/013-selenium-manager/Pasted-20240910-3_hu_211d5f165fb9d79f.webp 480w, https://chengxiaqiucao.github.io/post/013-selenium-manager/Pasted-20240910-3_hu_233f35873976e072.webp 1024w"
loading="lazy"
class="gallery-image"
data-flex-grow="287"
data-flex-basis="689px"
>
&lt;/p>
&lt;p>What Selenium calls here is the Selenium-manager command-line program&lt;/p>
&lt;p>We can directly execute this program and add &lt;code>--help&lt;/code> to see the supported parameters&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;span class="lnt">12
&lt;/span>&lt;span class="lnt">13
&lt;/span>&lt;span class="lnt">14
&lt;/span>&lt;span class="lnt">15
&lt;/span>&lt;span class="lnt">16
&lt;/span>&lt;span class="lnt">17
&lt;/span>&lt;span class="lnt">18
&lt;/span>&lt;span class="lnt">19
&lt;/span>&lt;span class="lnt">20
&lt;/span>&lt;span class="lnt">21
&lt;/span>&lt;span class="lnt">22
&lt;/span>&lt;span class="lnt">23
&lt;/span>&lt;span class="lnt">24
&lt;/span>&lt;span class="lnt">25
&lt;/span>&lt;span class="lnt">26
&lt;/span>&lt;span class="lnt">27
&lt;/span>&lt;span class="lnt">28
&lt;/span>&lt;span class="lnt">29
&lt;/span>&lt;span class="lnt">30
&lt;/span>&lt;span class="lnt">31
&lt;/span>&lt;span class="lnt">32
&lt;/span>&lt;span class="lnt">33
&lt;/span>&lt;span class="lnt">34
&lt;/span>&lt;span class="lnt">35
&lt;/span>&lt;span class="lnt">36
&lt;/span>&lt;span class="lnt">37
&lt;/span>&lt;span class="lnt">38
&lt;/span>&lt;span class="lnt">39
&lt;/span>&lt;span class="lnt">40
&lt;/span>&lt;span class="lnt">41
&lt;/span>&lt;span class="lnt">42
&lt;/span>&lt;span class="lnt">43
&lt;/span>&lt;span class="lnt">44
&lt;/span>&lt;span class="lnt">45
&lt;/span>&lt;span class="lnt">46
&lt;/span>&lt;span class="lnt">47
&lt;/span>&lt;span class="lnt">48
&lt;/span>&lt;span class="lnt">49
&lt;/span>&lt;span class="lnt">50
&lt;/span>&lt;span class="lnt">51
&lt;/span>&lt;span class="lnt">52
&lt;/span>&lt;span class="lnt">53
&lt;/span>&lt;span class="lnt">54
&lt;/span>&lt;span class="lnt">55
&lt;/span>&lt;span class="lnt">56
&lt;/span>&lt;span class="lnt">57
&lt;/span>&lt;span class="lnt">58
&lt;/span>&lt;span class="lnt">59
&lt;/span>&lt;span class="lnt">60
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-gdscript3" data-lang="gdscript3">&lt;span class="line">&lt;span class="cl">&lt;span class="n">selenium&lt;/span>&lt;span class="o">-&lt;/span>&lt;span class="n">manager&lt;/span> &lt;span class="mf">0.4&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="mi">24&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">Selenium&lt;/span> &lt;span class="n">Manager&lt;/span> &lt;span class="n">is&lt;/span> &lt;span class="n">a&lt;/span> &lt;span class="n">CLI&lt;/span> &lt;span class="k">tool&lt;/span> &lt;span class="n">that&lt;/span> &lt;span class="n">automatically&lt;/span> &lt;span class="n">manages&lt;/span> &lt;span class="n">the&lt;/span> &lt;span class="n">browser&lt;/span>&lt;span class="o">/&lt;/span>&lt;span class="n">driver&lt;/span> &lt;span class="n">infrastructure&lt;/span> &lt;span class="n">required&lt;/span> &lt;span class="n">by&lt;/span> &lt;span class="n">Selenium&lt;/span>&lt;span class="o">.&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">Usage&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="n">selenium&lt;/span>&lt;span class="o">-&lt;/span>&lt;span class="n">manager&lt;/span> &lt;span class="p">[&lt;/span>&lt;span class="n">OPTIONS&lt;/span>&lt;span class="p">]&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">Options&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="o">--&lt;/span>&lt;span class="n">browser&lt;/span> &lt;span class="o">&amp;lt;&lt;/span>&lt;span class="n">BROWSER&lt;/span>&lt;span class="o">&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">Browser&lt;/span> &lt;span class="n">name&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="n">chrome&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">firefox&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">edge&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">iexplorer&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">safari&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">safaritp&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="ow">or&lt;/span> &lt;span class="n">webview2&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="o">--&lt;/span>&lt;span class="n">driver&lt;/span> &lt;span class="o">&amp;lt;&lt;/span>&lt;span class="n">DRIVER&lt;/span>&lt;span class="o">&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">Driver&lt;/span> &lt;span class="n">name&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="n">chromedriver&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">geckodriver&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">msedgedriver&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">IEDriverServer&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="ow">or&lt;/span> &lt;span class="n">safaridriver&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="o">--&lt;/span>&lt;span class="n">grid&lt;/span> &lt;span class="p">[&lt;/span>&lt;span class="o">&amp;lt;&lt;/span>&lt;span class="n">GRID_VERSION&lt;/span>&lt;span class="o">&amp;gt;&lt;/span>&lt;span class="p">]&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">Selenium&lt;/span> &lt;span class="n">Grid&lt;/span>&lt;span class="o">.&lt;/span> &lt;span class="n">If&lt;/span> &lt;span class="n">version&lt;/span> &lt;span class="n">is&lt;/span> &lt;span class="ow">not&lt;/span> &lt;span class="n">provided&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">the&lt;/span> &lt;span class="n">latest&lt;/span> &lt;span class="n">version&lt;/span> &lt;span class="n">is&lt;/span> &lt;span class="n">downloaded&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="o">--&lt;/span>&lt;span class="n">driver&lt;/span>&lt;span class="o">-&lt;/span>&lt;span class="n">version&lt;/span> &lt;span class="o">&amp;lt;&lt;/span>&lt;span class="n">DRIVER_VERSION&lt;/span>&lt;span class="o">&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">Driver&lt;/span> &lt;span class="n">version&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="n">e&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">g&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="mf">106.0&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="mf">5249.61&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="mf">0.31&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="mi">0&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">etc&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="o">--&lt;/span>&lt;span class="n">browser&lt;/span>&lt;span class="o">-&lt;/span>&lt;span class="n">version&lt;/span> &lt;span class="o">&amp;lt;&lt;/span>&lt;span class="n">BROWSER_VERSION&lt;/span>&lt;span class="o">&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">Major&lt;/span> &lt;span class="n">browser&lt;/span> &lt;span class="n">version&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="n">e&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">g&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="mi">105&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="mi">106&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">etc&lt;/span>&lt;span class="o">.&lt;/span> &lt;span class="n">Also&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="n">beta&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">dev&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">canary&lt;/span> &lt;span class="o">-&lt;/span>&lt;span class="ow">or&lt;/span> &lt;span class="n">nightly&lt;/span>&lt;span class="o">-&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="ow">and&lt;/span> &lt;span class="n">esr&lt;/span> &lt;span class="o">-&lt;/span>&lt;span class="ow">in&lt;/span> &lt;span class="n">Firefox&lt;/span>&lt;span class="o">-&lt;/span> &lt;span class="n">are&lt;/span> &lt;span class="n">accepted&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="o">--&lt;/span>&lt;span class="n">browser&lt;/span>&lt;span class="o">-&lt;/span>&lt;span class="n">path&lt;/span> &lt;span class="o">&amp;lt;&lt;/span>&lt;span class="n">BROWSER_PATH&lt;/span>&lt;span class="o">&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">Browser&lt;/span> &lt;span class="n">path&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="n">absolute&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="k">for&lt;/span> &lt;span class="n">browser&lt;/span> &lt;span class="n">version&lt;/span> &lt;span class="n">detection&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="n">e&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">g&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="o">/&lt;/span>&lt;span class="n">usr&lt;/span>&lt;span class="o">/&lt;/span>&lt;span class="n">bin&lt;/span>&lt;span class="o">/&lt;/span>&lt;span class="n">google&lt;/span>&lt;span class="o">-&lt;/span>&lt;span class="n">chrome&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="s2">&amp;#34;/Applications/Google Chrome.app/Contents/MacOS/Google Chrome&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="s2">&amp;#34;C:\Program Files\Google\Chrome\Application\chrome.exe&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="o">--&lt;/span>&lt;span class="n">driver&lt;/span>&lt;span class="o">-&lt;/span>&lt;span class="n">mirror&lt;/span>&lt;span class="o">-&lt;/span>&lt;span class="n">url&lt;/span> &lt;span class="o">&amp;lt;&lt;/span>&lt;span class="n">DRIVER_MIRROR_URL&lt;/span>&lt;span class="o">&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">Mirror&lt;/span> &lt;span class="k">for&lt;/span> &lt;span class="n">driver&lt;/span> &lt;span class="n">repositories&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="n">e&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">g&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">https&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="o">//&lt;/span>&lt;span class="n">registry&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">npmmirror&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">com&lt;/span>&lt;span class="o">/-/&lt;/span>&lt;span class="n">binary&lt;/span>&lt;span class="o">/&lt;/span>&lt;span class="n">chromedriver&lt;/span>&lt;span class="o">/&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="o">--&lt;/span>&lt;span class="n">browser&lt;/span>&lt;span class="o">-&lt;/span>&lt;span class="n">mirror&lt;/span>&lt;span class="o">-&lt;/span>&lt;span class="n">url&lt;/span> &lt;span class="o">&amp;lt;&lt;/span>&lt;span class="n">BROWSER_MIRROR_URL&lt;/span>&lt;span class="o">&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">Mirror&lt;/span> &lt;span class="k">for&lt;/span> &lt;span class="n">browser&lt;/span> &lt;span class="n">repositories&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="o">--&lt;/span>&lt;span class="n">output&lt;/span> &lt;span class="o">&amp;lt;&lt;/span>&lt;span class="n">OUTPUT&lt;/span>&lt;span class="o">&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">Output&lt;/span> &lt;span class="n">type&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="n">LOGGER&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="n">using&lt;/span> &lt;span class="n">INFO&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">WARN&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">etc&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="p">),&lt;/span> &lt;span class="n">JSON&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="n">custom&lt;/span> &lt;span class="n">JSON&lt;/span> &lt;span class="n">notation&lt;/span>&lt;span class="p">),&lt;/span> &lt;span class="n">SHELL&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="n">Unix&lt;/span>&lt;span class="o">-&lt;/span>&lt;span class="n">like&lt;/span>&lt;span class="p">),&lt;/span> &lt;span class="ow">or&lt;/span> &lt;span class="n">MIXED&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="n">INFO&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">WARN&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">DEBUG&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">etc&lt;/span>&lt;span class="o">.&lt;/span> &lt;span class="n">to&lt;/span> &lt;span class="n">stderr&lt;/span> &lt;span class="ow">and&lt;/span> &lt;span class="n">minimal&lt;/span> &lt;span class="n">JSON&lt;/span> &lt;span class="n">to&lt;/span> &lt;span class="n">stdout&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="p">[&lt;/span>&lt;span class="n">default&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="n">LOGGER&lt;/span>&lt;span class="p">]&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="o">--&lt;/span>&lt;span class="n">os&lt;/span> &lt;span class="o">&amp;lt;&lt;/span>&lt;span class="ne">OS&lt;/span>&lt;span class="o">&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">Operating&lt;/span> &lt;span class="n">system&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="n">i&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">e&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">windows&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">linux&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="ow">or&lt;/span> &lt;span class="n">macos&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="o">--&lt;/span>&lt;span class="n">arch&lt;/span> &lt;span class="o">&amp;lt;&lt;/span>&lt;span class="n">ARCH&lt;/span>&lt;span class="o">&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">System&lt;/span> &lt;span class="n">architecture&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="n">i&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">e&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">x32&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">x64&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="ow">or&lt;/span> &lt;span class="n">arm64&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="o">--&lt;/span>&lt;span class="n">proxy&lt;/span> &lt;span class="o">&amp;lt;&lt;/span>&lt;span class="n">PROXY&lt;/span>&lt;span class="o">&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">HTTP&lt;/span> &lt;span class="n">proxy&lt;/span> &lt;span class="k">for&lt;/span> &lt;span class="n">network&lt;/span> &lt;span class="n">connection&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="n">e&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">g&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">https&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="o">//&lt;/span>&lt;span class="n">myproxy&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">net&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="mi">8080&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="o">--&lt;/span>&lt;span class="n">timeout&lt;/span> &lt;span class="o">&amp;lt;&lt;/span>&lt;span class="n">TIMEOUT&lt;/span>&lt;span class="o">&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">Timeout&lt;/span> &lt;span class="k">for&lt;/span> &lt;span class="n">network&lt;/span> &lt;span class="n">requests&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="ow">in&lt;/span> &lt;span class="n">seconds&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="p">[&lt;/span>&lt;span class="n">default&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mi">300&lt;/span>&lt;span class="p">]&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="o">--&lt;/span>&lt;span class="n">ttl&lt;/span> &lt;span class="o">&amp;lt;&lt;/span>&lt;span class="n">TTL&lt;/span>&lt;span class="o">&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">TTL&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="n">time&lt;/span>&lt;span class="o">-&lt;/span>&lt;span class="n">to&lt;/span>&lt;span class="o">-&lt;/span>&lt;span class="n">live&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="k">for&lt;/span> &lt;span class="n">discovered&lt;/span> &lt;span class="n">versions&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="n">online&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="n">of&lt;/span> &lt;span class="n">drivers&lt;/span> &lt;span class="ow">and&lt;/span> &lt;span class="n">browsers&lt;/span> &lt;span class="p">[&lt;/span>&lt;span class="n">default&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mi">3600&lt;/span>&lt;span class="p">]&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="o">--&lt;/span>&lt;span class="n">cache&lt;/span>&lt;span class="o">-&lt;/span>&lt;span class="n">path&lt;/span> &lt;span class="o">&amp;lt;&lt;/span>&lt;span class="n">CACHE_PATH&lt;/span>&lt;span class="o">&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">Local&lt;/span> &lt;span class="n">folder&lt;/span> &lt;span class="n">used&lt;/span> &lt;span class="n">to&lt;/span> &lt;span class="n">store&lt;/span> &lt;span class="n">downloaded&lt;/span> &lt;span class="n">assets&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="n">drivers&lt;/span> &lt;span class="ow">and&lt;/span> &lt;span class="n">browsers&lt;/span>&lt;span class="p">),&lt;/span> &lt;span class="n">local&lt;/span> &lt;span class="n">metadata&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="ow">and&lt;/span> &lt;span class="n">configuration&lt;/span> &lt;span class="n">file&lt;/span> &lt;span class="p">[&lt;/span>&lt;span class="n">default&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="o">~/.&lt;/span>&lt;span class="n">cache&lt;/span>&lt;span class="o">/&lt;/span>&lt;span class="n">selenium&lt;/span>&lt;span class="p">]&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="o">--&lt;/span>&lt;span class="n">clear&lt;/span>&lt;span class="o">-&lt;/span>&lt;span class="n">cache&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">Clear&lt;/span> &lt;span class="n">cache&lt;/span> &lt;span class="n">folder&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="o">~/.&lt;/span>&lt;span class="n">cache&lt;/span>&lt;span class="o">/&lt;/span>&lt;span class="n">selenium&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="o">--&lt;/span>&lt;span class="n">clear&lt;/span>&lt;span class="o">-&lt;/span>&lt;span class="n">metadata&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">Clear&lt;/span> &lt;span class="n">metadata&lt;/span> &lt;span class="n">file&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="o">~/.&lt;/span>&lt;span class="n">cache&lt;/span>&lt;span class="o">/&lt;/span>&lt;span class="n">selenium&lt;/span>&lt;span class="o">/&lt;/span>&lt;span class="n">selenium&lt;/span>&lt;span class="o">-&lt;/span>&lt;span class="n">manager&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">json&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="o">--&lt;/span>&lt;span class="n">debug&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">Display&lt;/span> &lt;span class="n">DEBUG&lt;/span> &lt;span class="n">messages&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="o">--&lt;/span>&lt;span class="n">trace&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">Display&lt;/span> &lt;span class="n">TRACE&lt;/span> &lt;span class="n">messages&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="o">--&lt;/span>&lt;span class="nb">log&lt;/span>&lt;span class="o">-&lt;/span>&lt;span class="n">level&lt;/span> &lt;span class="o">&amp;lt;&lt;/span>&lt;span class="n">LOG_LEVEL&lt;/span>&lt;span class="o">&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">Level&lt;/span> &lt;span class="k">for&lt;/span> &lt;span class="n">output&lt;/span> &lt;span class="n">messages&lt;/span>&lt;span class="o">.&lt;/span> &lt;span class="n">The&lt;/span> &lt;span class="n">possible&lt;/span> &lt;span class="n">values&lt;/span> &lt;span class="n">are&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="n">info&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">debug&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">trace&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">warn&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">error&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="o">--&lt;/span>&lt;span class="n">offline&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">Offline&lt;/span> &lt;span class="n">mode&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="n">i&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">e&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">disabling&lt;/span> &lt;span class="n">network&lt;/span> &lt;span class="n">requests&lt;/span> &lt;span class="ow">and&lt;/span> &lt;span class="n">downloads&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="o">--&lt;/span>&lt;span class="n">force&lt;/span>&lt;span class="o">-&lt;/span>&lt;span class="n">browser&lt;/span>&lt;span class="o">-&lt;/span>&lt;span class="n">download&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">Force&lt;/span> &lt;span class="n">to&lt;/span> &lt;span class="n">download&lt;/span> &lt;span class="n">browser&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="n">even&lt;/span> &lt;span class="n">when&lt;/span> &lt;span class="n">browser&lt;/span> &lt;span class="n">is&lt;/span> &lt;span class="n">already&lt;/span> &lt;span class="ow">in&lt;/span> &lt;span class="n">the&lt;/span> &lt;span class="n">system&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="o">--&lt;/span>&lt;span class="n">avoid&lt;/span>&lt;span class="o">-&lt;/span>&lt;span class="n">browser&lt;/span>&lt;span class="o">-&lt;/span>&lt;span class="n">download&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">Avoid&lt;/span> &lt;span class="n">to&lt;/span> &lt;span class="n">download&lt;/span> &lt;span class="n">browser&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="n">even&lt;/span> &lt;span class="n">when&lt;/span> &lt;span class="n">browser&lt;/span>&lt;span class="o">-&lt;/span>&lt;span class="n">version&lt;/span> &lt;span class="n">is&lt;/span> &lt;span class="n">specified&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="o">--&lt;/span>&lt;span class="n">language&lt;/span>&lt;span class="o">-&lt;/span>&lt;span class="n">binding&lt;/span> &lt;span class="o">&amp;lt;&lt;/span>&lt;span class="n">LANGUAGE_BINDING&lt;/span>&lt;span class="o">&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">Selenium&lt;/span> &lt;span class="n">language&lt;/span> &lt;span class="n">bindings&lt;/span> &lt;span class="n">that&lt;/span> &lt;span class="n">invokes&lt;/span> &lt;span class="n">Selenium&lt;/span> &lt;span class="n">Manager&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="n">e&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">g&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">Java&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">JavaScript&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">Python&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">DotNet&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">Ruby&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="o">--&lt;/span>&lt;span class="n">avoid&lt;/span>&lt;span class="o">-&lt;/span>&lt;span class="n">stats&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">Avoid&lt;/span> &lt;span class="n">sends&lt;/span> &lt;span class="n">usage&lt;/span> &lt;span class="n">statistics&lt;/span> &lt;span class="n">to&lt;/span> &lt;span class="n">plausible&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">io&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="o">-&lt;/span>&lt;span class="n">h&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="o">--&lt;/span>&lt;span class="n">help&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">Print&lt;/span> &lt;span class="n">help&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="o">-&lt;/span>&lt;span class="n">V&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="o">--&lt;/span>&lt;span class="n">version&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">Print&lt;/span> &lt;span class="n">version&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>We can execute it to take a look at the output information here; actually, when selenium executes, it is precisely this command-line program that it calls&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;span class="lnt">12
&lt;/span>&lt;span class="lnt">13
&lt;/span>&lt;span class="lnt">14
&lt;/span>&lt;span class="lnt">15
&lt;/span>&lt;span class="lnt">16
&lt;/span>&lt;span class="lnt">17
&lt;/span>&lt;span class="lnt">18
&lt;/span>&lt;span class="lnt">19
&lt;/span>&lt;span class="lnt">20
&lt;/span>&lt;span class="lnt">21
&lt;/span>&lt;span class="lnt">22
&lt;/span>&lt;span class="lnt">23
&lt;/span>&lt;span class="lnt">24
&lt;/span>&lt;span class="lnt">25
&lt;/span>&lt;span class="lnt">26
&lt;/span>&lt;span class="lnt">27
&lt;/span>&lt;span class="lnt">28
&lt;/span>&lt;span class="lnt">29
&lt;/span>&lt;span class="lnt">30
&lt;/span>&lt;span class="lnt">31
&lt;/span>&lt;span class="lnt">32
&lt;/span>&lt;span class="lnt">33
&lt;/span>&lt;span class="lnt">34
&lt;/span>&lt;span class="lnt">35
&lt;/span>&lt;span class="lnt">36
&lt;/span>&lt;span class="lnt">37
&lt;/span>&lt;span class="lnt">38
&lt;/span>&lt;span class="lnt">39
&lt;/span>&lt;span class="lnt">40
&lt;/span>&lt;span class="lnt">41
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-gdscript3" data-lang="gdscript3">&lt;span class="line">&lt;span class="cl">&lt;span class="o">&amp;gt;&lt;/span>&lt;span class="n">selenium&lt;/span>&lt;span class="o">-&lt;/span>&lt;span class="n">manager&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">exe&lt;/span> &lt;span class="o">--&lt;/span>&lt;span class="n">browser&lt;/span> &lt;span class="n">firefox&lt;/span> &lt;span class="o">--&lt;/span>&lt;span class="n">debug&lt;/span> &lt;span class="c1"># the debug parameter shows detailed output&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">[&lt;/span>&lt;span class="mi">2024&lt;/span>&lt;span class="o">-&lt;/span>&lt;span class="mi">09&lt;/span>&lt;span class="o">-&lt;/span>&lt;span class="mi">10&lt;/span>&lt;span class="n">T13&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="mi">35&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="mf">56.007&lt;/span>&lt;span class="n">Z&lt;/span> &lt;span class="n">DEBUG&lt;/span>&lt;span class="p">]&lt;/span> &lt;span class="n">geckodriver&lt;/span> &lt;span class="ow">not&lt;/span> &lt;span class="n">found&lt;/span> &lt;span class="ow">in&lt;/span> &lt;span class="n">PATH&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># First, determine whether a driver exists in the system PATH based on the specified browser&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">[&lt;/span>&lt;span class="mi">2024&lt;/span>&lt;span class="o">-&lt;/span>&lt;span class="mi">09&lt;/span>&lt;span class="o">-&lt;/span>&lt;span class="mi">10&lt;/span>&lt;span class="n">T13&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="mi">35&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="mf">56.010&lt;/span>&lt;span class="n">Z&lt;/span> &lt;span class="n">DEBUG&lt;/span>&lt;span class="p">]&lt;/span> &lt;span class="n">firefox&lt;/span> &lt;span class="ow">not&lt;/span> &lt;span class="n">found&lt;/span> &lt;span class="ow">in&lt;/span> &lt;span class="n">PATH&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># Likewise, based on whether the PATH contains the firefox browser installation path&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">[&lt;/span>&lt;span class="mi">2024&lt;/span>&lt;span class="o">-&lt;/span>&lt;span class="mi">09&lt;/span>&lt;span class="o">-&lt;/span>&lt;span class="mi">10&lt;/span>&lt;span class="n">T13&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="mi">35&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="mf">56.010&lt;/span>&lt;span class="n">Z&lt;/span> &lt;span class="n">DEBUG&lt;/span>&lt;span class="p">]&lt;/span> &lt;span class="n">Running&lt;/span> &lt;span class="n">command&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="n">REG&lt;/span> &lt;span class="n">QUERY&lt;/span> &lt;span class="n">HKCU&lt;/span>\&lt;span class="n">Software&lt;/span>\&lt;span class="n">Mozilla&lt;/span>\&lt;span class="n">Mozilla&lt;/span> &lt;span class="n">Firefox&lt;/span> &lt;span class="o">/&lt;/span>&lt;span class="n">v&lt;/span> &lt;span class="n">CurrentVersion&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">[&lt;/span>&lt;span class="mi">2024&lt;/span>&lt;span class="o">-&lt;/span>&lt;span class="mi">09&lt;/span>&lt;span class="o">-&lt;/span>&lt;span class="mi">10&lt;/span>&lt;span class="n">T13&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="mi">35&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="mf">56.034&lt;/span>&lt;span class="n">Z&lt;/span> &lt;span class="n">DEBUG&lt;/span>&lt;span class="p">]&lt;/span> &lt;span class="n">Output&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">[&lt;/span>&lt;span class="mi">2024&lt;/span>&lt;span class="o">-&lt;/span>&lt;span class="mi">09&lt;/span>&lt;span class="o">-&lt;/span>&lt;span class="mi">10&lt;/span>&lt;span class="n">T13&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="mi">35&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="mf">56.036&lt;/span>&lt;span class="n">Z&lt;/span> &lt;span class="n">DEBUG&lt;/span>&lt;span class="p">]&lt;/span> &lt;span class="n">firefox&lt;/span> &lt;span class="ow">not&lt;/span> &lt;span class="n">found&lt;/span> &lt;span class="ow">in&lt;/span> &lt;span class="n">the&lt;/span> &lt;span class="n">system&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># Find the firefox browser installation path through the registry&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">[&lt;/span>&lt;span class="mi">2024&lt;/span>&lt;span class="o">-&lt;/span>&lt;span class="mi">09&lt;/span>&lt;span class="o">-&lt;/span>&lt;span class="mi">10&lt;/span>&lt;span class="n">T13&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="mi">35&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="mf">56.037&lt;/span>&lt;span class="n">Z&lt;/span> &lt;span class="n">DEBUG&lt;/span>&lt;span class="p">]&lt;/span> &lt;span class="n">Required&lt;/span> &lt;span class="n">browser&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="n">firefox&lt;/span> &lt;span class="mf">130.0&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="o">--&lt;/span> &lt;span class="n">No&lt;/span> &lt;span class="n">browser&lt;/span> &lt;span class="n">version&lt;/span> &lt;span class="n">specified&lt;/span>&lt;span class="p">;&lt;/span> &lt;span class="n">obtain&lt;/span> &lt;span class="n">the&lt;/span> &lt;span class="n">latest&lt;/span> &lt;span class="n">version&lt;/span> &lt;span class="n">based&lt;/span> &lt;span class="n">on&lt;/span> &lt;span class="n">online&lt;/span> &lt;span class="n">information&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">[&lt;/span>&lt;span class="mi">2024&lt;/span>&lt;span class="o">-&lt;/span>&lt;span class="mi">09&lt;/span>&lt;span class="o">-&lt;/span>&lt;span class="mi">10&lt;/span>&lt;span class="n">T13&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="mi">35&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="mf">56.037&lt;/span>&lt;span class="n">Z&lt;/span> &lt;span class="n">DEBUG&lt;/span>&lt;span class="p">]&lt;/span> &lt;span class="n">Downloading&lt;/span> &lt;span class="n">firefox&lt;/span> &lt;span class="mf">130.0&lt;/span> &lt;span class="n">from&lt;/span> &lt;span class="n">https&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="o">//&lt;/span>&lt;span class="n">ftp&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">mozilla&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">org&lt;/span>&lt;span class="o">/&lt;/span>&lt;span class="n">pub&lt;/span>&lt;span class="o">/&lt;/span>&lt;span class="n">firefox&lt;/span>&lt;span class="o">/&lt;/span>&lt;span class="n">releases&lt;/span>&lt;span class="o">/&lt;/span>&lt;span class="mf">130.0&lt;/span>&lt;span class="o">/&lt;/span>&lt;span class="n">win64&lt;/span>&lt;span class="o">/&lt;/span>&lt;span class="n">en&lt;/span>&lt;span class="o">-&lt;/span>&lt;span class="n">US&lt;/span>&lt;span class="o">/&lt;/span>&lt;span class="n">Firefox&lt;/span>&lt;span class="o">%&lt;/span>&lt;span class="mi">20&lt;/span>&lt;span class="n">Setup&lt;/span>&lt;span class="o">%&lt;/span>&lt;span class="mf">20130.0&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">exe&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># Download from the official site&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">[&lt;/span>&lt;span class="mi">2024&lt;/span>&lt;span class="o">-&lt;/span>&lt;span class="mi">09&lt;/span>&lt;span class="o">-&lt;/span>&lt;span class="mi">10&lt;/span>&lt;span class="n">T13&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="mi">36&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="mf">13.320&lt;/span>&lt;span class="n">Z&lt;/span> &lt;span class="n">DEBUG&lt;/span>&lt;span class="p">]&lt;/span> &lt;span class="n">firefox&lt;/span> &lt;span class="mf">130.0&lt;/span> &lt;span class="n">is&lt;/span> &lt;span class="n">available&lt;/span> &lt;span class="n">at&lt;/span> &lt;span class="n">C&lt;/span>&lt;span class="p">:&lt;/span>\&lt;span class="n">Users&lt;/span>\&lt;span class="n">Administrator&lt;/span>\&lt;span class="o">.&lt;/span>&lt;span class="n">cache&lt;/span>\&lt;span class="n">selenium&lt;/span>\&lt;span class="n">firefox&lt;/span>\&lt;span class="n">win64&lt;/span>\&lt;span class="mf">130.0&lt;/span>\&lt;span class="n">firefox&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">exe&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># Download complete&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">[&lt;/span>&lt;span class="mi">2024&lt;/span>&lt;span class="o">-&lt;/span>&lt;span class="mi">09&lt;/span>&lt;span class="o">-&lt;/span>&lt;span class="mi">10&lt;/span>&lt;span class="n">T13&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="mi">36&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="mf">14.367&lt;/span>&lt;span class="n">Z&lt;/span> &lt;span class="n">DEBUG&lt;/span>&lt;span class="p">]&lt;/span> &lt;span class="n">Valid&lt;/span> &lt;span class="n">geckodriver&lt;/span> &lt;span class="n">versions&lt;/span> &lt;span class="k">for&lt;/span> &lt;span class="n">firefox&lt;/span> &lt;span class="mi">130&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="p">[&lt;/span>&lt;span class="s2">&amp;#34;0.35.0&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="s2">&amp;#34;0.34.0&amp;#34;&lt;/span>&lt;span class="p">]&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># Get available driver versions&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">[&lt;/span>&lt;span class="mi">2024&lt;/span>&lt;span class="o">-&lt;/span>&lt;span class="mi">09&lt;/span>&lt;span class="o">-&lt;/span>&lt;span class="mi">10&lt;/span>&lt;span class="n">T13&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="mi">36&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="mf">14.369&lt;/span>&lt;span class="n">Z&lt;/span> &lt;span class="n">DEBUG&lt;/span>&lt;span class="p">]&lt;/span> &lt;span class="n">Required&lt;/span> &lt;span class="n">driver&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="n">geckodriver&lt;/span> &lt;span class="mf">0.35&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="mi">0&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">[&lt;/span>&lt;span class="mi">2024&lt;/span>&lt;span class="o">-&lt;/span>&lt;span class="mi">09&lt;/span>&lt;span class="o">-&lt;/span>&lt;span class="mi">10&lt;/span>&lt;span class="n">T13&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="mi">36&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="mf">14.372&lt;/span>&lt;span class="n">Z&lt;/span> &lt;span class="n">DEBUG&lt;/span>&lt;span class="p">]&lt;/span> &lt;span class="n">Downloading&lt;/span> &lt;span class="n">geckodriver&lt;/span> &lt;span class="mf">0.35&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="mi">0&lt;/span> &lt;span class="n">from&lt;/span> &lt;span class="n">https&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="o">//&lt;/span>&lt;span class="n">github&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">com&lt;/span>&lt;span class="o">/&lt;/span>&lt;span class="n">mozilla&lt;/span>&lt;span class="o">/&lt;/span>&lt;span class="n">geckodriver&lt;/span>&lt;span class="o">/&lt;/span>&lt;span class="n">releases&lt;/span>&lt;span class="o">/&lt;/span>&lt;span class="n">download&lt;/span>&lt;span class="o">/&lt;/span>&lt;span class="n">v0&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="mf">35.0&lt;/span>&lt;span class="o">/&lt;/span>&lt;span class="n">geckodriver&lt;/span>&lt;span class="o">-&lt;/span>&lt;span class="n">v0&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="mf">35.0&lt;/span>&lt;span class="o">-&lt;/span>&lt;span class="n">win64&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">zip&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># Download the corresponding driver&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">[&lt;/span>&lt;span class="mi">2024&lt;/span>&lt;span class="o">-&lt;/span>&lt;span class="mi">09&lt;/span>&lt;span class="o">-&lt;/span>&lt;span class="mi">10&lt;/span>&lt;span class="n">T13&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="mi">36&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="mf">18.238&lt;/span>&lt;span class="n">Z&lt;/span> &lt;span class="n">INFO&lt;/span> &lt;span class="p">]&lt;/span> &lt;span class="n">Driver&lt;/span> &lt;span class="n">path&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="n">C&lt;/span>&lt;span class="p">:&lt;/span>\&lt;span class="n">Users&lt;/span>\&lt;span class="n">Administrator&lt;/span>\&lt;span class="o">.&lt;/span>&lt;span class="n">cache&lt;/span>\&lt;span class="n">selenium&lt;/span>\&lt;span class="n">geckodriver&lt;/span>\&lt;span class="n">win64&lt;/span>\&lt;span class="mf">0.35&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="mi">0&lt;/span>\&lt;span class="n">geckodriver&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">exe&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">[&lt;/span>&lt;span class="mi">2024&lt;/span>&lt;span class="o">-&lt;/span>&lt;span class="mi">09&lt;/span>&lt;span class="o">-&lt;/span>&lt;span class="mi">10&lt;/span>&lt;span class="n">T13&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="mi">36&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="mf">18.239&lt;/span>&lt;span class="n">Z&lt;/span> &lt;span class="n">INFO&lt;/span> &lt;span class="p">]&lt;/span> &lt;span class="n">Browser&lt;/span> &lt;span class="n">path&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="n">C&lt;/span>&lt;span class="p">:&lt;/span>\&lt;span class="n">Users&lt;/span>\&lt;span class="n">Administrator&lt;/span>\&lt;span class="o">.&lt;/span>&lt;span class="n">cache&lt;/span>\&lt;span class="n">selenium&lt;/span>\&lt;span class="n">firefox&lt;/span>\&lt;span class="n">win64&lt;/span>\&lt;span class="mf">130.0&lt;/span>\&lt;span class="n">firefox&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">exe&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># Output the browser and driver paths; this is actually the information returned when selenium calls it&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>And besides Browser and Driver, Selenium-manager actually also supports downloading grid versions. Through the &lt;code>--grid&lt;/code> parameter, the latest version of grid can be downloaded directly.&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;span class="lnt">3
&lt;/span>&lt;span class="lnt">4
&lt;/span>&lt;span class="lnt">5
&lt;/span>&lt;span class="lnt">6
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-gdscript3" data-lang="gdscript3">&lt;span class="line">&lt;span class="cl">&lt;span class="o">&amp;gt;&lt;/span> &lt;span class="n">selenium&lt;/span>&lt;span class="o">-&lt;/span>&lt;span class="n">manager&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">exe&lt;/span> &lt;span class="o">--&lt;/span>&lt;span class="n">grid&lt;/span> &lt;span class="o">--&lt;/span>&lt;span class="n">debug&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">[&lt;/span>&lt;span class="mi">2024&lt;/span>&lt;span class="o">-&lt;/span>&lt;span class="mi">09&lt;/span>&lt;span class="o">-&lt;/span>&lt;span class="mi">10&lt;/span>&lt;span class="n">T13&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="mi">47&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="mf">41.793&lt;/span>&lt;span class="n">Z&lt;/span> &lt;span class="n">DEBUG&lt;/span>&lt;span class="p">]&lt;/span> &lt;span class="n">Sending&lt;/span> &lt;span class="n">stats&lt;/span> &lt;span class="n">to&lt;/span> &lt;span class="n">Plausible&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="n">Props&lt;/span> &lt;span class="p">{&lt;/span> &lt;span class="n">browser&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;grid&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">browser_version&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">os&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;windows&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">arch&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;amd64&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">lang&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">selenium_version&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;4.24&amp;#34;&lt;/span> &lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">[&lt;/span>&lt;span class="mi">2024&lt;/span>&lt;span class="o">-&lt;/span>&lt;span class="mi">09&lt;/span>&lt;span class="o">-&lt;/span>&lt;span class="mi">10&lt;/span>&lt;span class="n">T13&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="mi">47&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="mf">41.795&lt;/span>&lt;span class="n">Z&lt;/span> &lt;span class="n">DEBUG&lt;/span>&lt;span class="p">]&lt;/span> &lt;span class="n">grid&lt;/span> &lt;span class="ow">not&lt;/span> &lt;span class="n">found&lt;/span> &lt;span class="ow">in&lt;/span> &lt;span class="n">the&lt;/span> &lt;span class="n">system&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">[&lt;/span>&lt;span class="mi">2024&lt;/span>&lt;span class="o">-&lt;/span>&lt;span class="mi">09&lt;/span>&lt;span class="o">-&lt;/span>&lt;span class="mi">10&lt;/span>&lt;span class="n">T13&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="mi">47&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="mf">43.667&lt;/span>&lt;span class="n">Z&lt;/span> &lt;span class="n">DEBUG&lt;/span>&lt;span class="p">]&lt;/span> &lt;span class="n">Required&lt;/span> &lt;span class="n">driver&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="n">selenium&lt;/span>&lt;span class="o">-&lt;/span>&lt;span class="n">server&lt;/span> &lt;span class="mf">4.24&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="mi">0&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">[&lt;/span>&lt;span class="mi">2024&lt;/span>&lt;span class="o">-&lt;/span>&lt;span class="mi">09&lt;/span>&lt;span class="o">-&lt;/span>&lt;span class="mi">10&lt;/span>&lt;span class="n">T13&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="mi">47&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="mf">43.669&lt;/span>&lt;span class="n">Z&lt;/span> &lt;span class="n">DEBUG&lt;/span>&lt;span class="p">]&lt;/span> &lt;span class="n">Downloading&lt;/span> &lt;span class="n">selenium&lt;/span>&lt;span class="o">-&lt;/span>&lt;span class="n">server&lt;/span> &lt;span class="mf">4.24&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="mi">0&lt;/span> &lt;span class="n">from&lt;/span> &lt;span class="n">https&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="o">//&lt;/span>&lt;span class="n">github&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">com&lt;/span>&lt;span class="o">/&lt;/span>&lt;span class="n">SeleniumHQ&lt;/span>&lt;span class="o">/&lt;/span>&lt;span class="n">selenium&lt;/span>&lt;span class="o">/&lt;/span>&lt;span class="n">releases&lt;/span>&lt;span class="o">/&lt;/span>&lt;span class="n">download&lt;/span>&lt;span class="o">/&lt;/span>&lt;span class="n">selenium&lt;/span>&lt;span class="o">-&lt;/span>&lt;span class="mf">4.24&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="mi">0&lt;/span>&lt;span class="o">/&lt;/span>&lt;span class="n">selenium&lt;/span>&lt;span class="o">-&lt;/span>&lt;span class="n">server&lt;/span>&lt;span class="o">-&lt;/span>&lt;span class="mf">4.24&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="mf">0.j&lt;/span>&lt;span class="n">ar&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">[&lt;/span>&lt;span class="mi">2024&lt;/span>&lt;span class="o">-&lt;/span>&lt;span class="mi">09&lt;/span>&lt;span class="o">-&lt;/span>&lt;span class="mi">10&lt;/span>&lt;span class="n">T13&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="mi">47&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="mf">51.547&lt;/span>&lt;span class="n">Z&lt;/span> &lt;span class="n">INFO&lt;/span> &lt;span class="p">]&lt;/span> &lt;span class="n">Driver&lt;/span> &lt;span class="n">path&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="n">C&lt;/span>&lt;span class="p">:&lt;/span>\&lt;span class="n">Users&lt;/span>\&lt;span class="n">Administrator&lt;/span>\&lt;span class="o">.&lt;/span>&lt;span class="n">cache&lt;/span>\&lt;span class="n">selenium&lt;/span>\&lt;span class="n">grid&lt;/span>\&lt;span class="mf">4.24&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="mi">0&lt;/span>\&lt;span class="n">selenium&lt;/span>&lt;span class="o">-&lt;/span>&lt;span class="n">server&lt;/span>&lt;span class="o">-&lt;/span>&lt;span class="mf">4.24&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="mf">0.j&lt;/span>&lt;span class="n">ar&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>From the introduction above, it can be seen that by introducing Selenium-manager, Selenium can now, during environment preparation, very flexibly achieve automatic acquisition and configuration of resources such as the browser, the driver, and even the grid server, greatly improving the convenience of using Selenium.&lt;/p></description></item><item><title>Fixture Scope in Pytest</title><link>https://chengxiaqiucao.github.io/en/post/018-pytest%E4%B8%ADfixture%E7%9A%84%E8%8C%83%E5%9B%B4/</link><pubDate>Wed, 28 Aug 2024 20:33:52 +0800</pubDate><guid>https://chengxiaqiucao.github.io/en/post/018-pytest%E4%B8%ADfixture%E7%9A%84%E8%8C%83%E5%9B%B4/</guid><description>&lt;p>pytest, as the most mainstream testing framework in the Python technology stack, is extremely powerful and flexible. Fixtures are at its core. Moreover, pytest also distinguishes different scopes for fixtures, which brings great flexibility to how we use them.&lt;/p>
&lt;p>Let us take a look below at the role of each different scope.&lt;/p>
&lt;h2 id="definition-of-fixture-scope">Definition of fixture scope
&lt;/h2>&lt;p>First, according to the official documentation, the scope of a fixture in Pytest supports five settings: &lt;code>function&lt;/code> (the default), &lt;code>classs&lt;/code>, &lt;code>module&lt;/code>, &lt;code>package&lt;/code>, and &lt;code>session&lt;/code>&lt;/p>
&lt;table>
&lt;thead>
&lt;tr>
&lt;th style="text-align: center">&lt;strong>Scope&lt;/strong>&lt;/th>
&lt;th style="text-align: left">&lt;strong>Description&lt;/strong>&lt;/th>
&lt;/tr>
&lt;/thead>
&lt;tbody>
&lt;tr>
&lt;td style="text-align: center">&lt;strong>function&lt;/strong>&lt;/td>
&lt;td style="text-align: left">Default value; takes effect for each test method (function), with a lifecycle at the test method level&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td style="text-align: center">&lt;strong>class&lt;/strong>&lt;/td>
&lt;td style="text-align: left">Takes effect for the test class, with a lifecycle at the test class level&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td style="text-align: center">&lt;strong>module&lt;/strong>&lt;/td>
&lt;td style="text-align: left">Takes effect for the test module, with a lifecycle at the module (file) level&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td style="text-align: center">&lt;strong>package&lt;/strong>&lt;/td>
&lt;td style="text-align: left">Takes effect for the test package, with a lifecycle at the test package (directory) level&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td style="text-align: center">&lt;strong>session&lt;/strong>&lt;/td>
&lt;td style="text-align: left">Takes effect for the test session, with a lifecycle at the session (one pytest run) level&lt;/td>
&lt;/tr>
&lt;/tbody>
&lt;/table>
&lt;p>Let us illustrate this with code below. Suppose we currently have the following code structure&lt;/p>
&lt;p>&lt;img src="https://chengxiaqiucao.github.io/post/018-pytest%E4%B8%ADfixture%E7%9A%84%E8%8C%83%E5%9B%B4/Pasted-20240901_hu_26d0c787adbb39a9.webp"
width="1024"
height="975"
srcset="https://chengxiaqiucao.github.io/post/018-pytest%E4%B8%ADfixture%E7%9A%84%E8%8C%83%E5%9B%B4/Pasted-20240901_hu_c1e9410c9726d53b.webp 480w, https://chengxiaqiucao.github.io/post/018-pytest%E4%B8%ADfixture%E7%9A%84%E8%8C%83%E5%9B%B4/Pasted-20240901_hu_26d0c787adbb39a9.webp 1024w"
loading="lazy"
class="gallery-image"
data-flex-grow="104"
data-flex-basis="251px"
>
&lt;/p>
&lt;p>&lt;code>run_params&lt;/code> is the method under test&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-python" data-lang="python">&lt;span class="line">&lt;span class="cl">&lt;span class="k">def&lt;/span> &lt;span class="nf">deal_params&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">p&lt;/span>&lt;span class="p">):&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nb">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="sa">f&lt;/span>&lt;span class="s2">&amp;#34;input :&lt;/span>&lt;span class="si">{&lt;/span>&lt;span class="n">p&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">if&lt;/span> &lt;span class="nb">type&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">p&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="ow">is&lt;/span> &lt;span class="nb">int&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">return&lt;/span> &lt;span class="n">p&lt;/span>&lt;span class="o">*&lt;/span>&lt;span class="mi">10&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">if&lt;/span> &lt;span class="nb">type&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">p&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="ow">is&lt;/span> &lt;span class="nb">str&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">return&lt;/span> &lt;span class="n">p&lt;/span>&lt;span class="o">*&lt;/span>&lt;span class="mi">3&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">if&lt;/span> &lt;span class="nb">type&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">p&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="ow">in&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="nb">tuple&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="nb">list&lt;/span>&lt;span class="p">):&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">return&lt;/span> &lt;span class="s2">&amp;#34;_&amp;#34;&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">join&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">p&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">else&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">raise&lt;/span> &lt;span class="ne">TypeError&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>&lt;code>test_ch_param&lt;/code> and &lt;code>test_fixture_scope&lt;/code> respectively define parameterization and the different test methods inside a test class&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;span class="lnt">3
&lt;/span>&lt;span class="lnt">4
&lt;/span>&lt;span class="lnt">5
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-python" data-lang="python">&lt;span class="line">&lt;span class="cl">&lt;span class="kn">import&lt;/span> &lt;span class="nn">pytest&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nd">@pytest.mark.parametrize&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s2">&amp;#34;param&amp;#34;&lt;/span>&lt;span class="p">,[&lt;/span>&lt;span class="mi">10&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="s2">&amp;#34;城下秋草&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="s2">&amp;#34;软件测试&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="s2">&amp;#34;示例&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="s2">&amp;#34;代码&amp;#34;&lt;/span>&lt;span class="p">)])&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="k">def&lt;/span> &lt;span class="nf">test_params_mark&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">param&lt;/span>&lt;span class="p">):&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nb">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">deal_params&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">param&lt;/span>&lt;span class="p">))&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;span class="lnt">12
&lt;/span>&lt;span class="lnt">13
&lt;/span>&lt;span class="lnt">14
&lt;/span>&lt;span class="lnt">15
&lt;/span>&lt;span class="lnt">16
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-python" data-lang="python">&lt;span class="line">&lt;span class="cl">&lt;span class="kn">import&lt;/span> &lt;span class="nn">pytest&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="k">class&lt;/span> &lt;span class="nc">TestFixtureScope1&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">def&lt;/span> &lt;span class="nf">test_int&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="bp">self&lt;/span>&lt;span class="p">):&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">assert&lt;/span> &lt;span class="n">deal_params&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="mi">2&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="o">==&lt;/span> &lt;span class="mi">20&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">def&lt;/span> &lt;span class="nf">test_str&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="bp">self&lt;/span>&lt;span class="p">):&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">assert&lt;/span> &lt;span class="n">deal_params&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s2">&amp;#34;秋草&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="o">==&lt;/span> &lt;span class="s2">&amp;#34;秋草秋草秋草&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="k">class&lt;/span> &lt;span class="nc">TestFixtureScope2&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">def&lt;/span> &lt;span class="nf">test_list&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="bp">self&lt;/span>&lt;span class="p">):&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">assert&lt;/span> &lt;span class="n">deal_params&lt;/span>&lt;span class="p">([&lt;/span>&lt;span class="s2">&amp;#34;城下&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>&lt;span class="s2">&amp;#34;秋草&amp;#34;&lt;/span>&lt;span class="p">])&lt;/span> &lt;span class="o">==&lt;/span> &lt;span class="s2">&amp;#34;城下_秋草&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">def&lt;/span> &lt;span class="nf">test_dict&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="bp">self&lt;/span>&lt;span class="p">):&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">with&lt;/span> &lt;span class="n">pytest&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">raises&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="ne">TypeError&lt;/span>&lt;span class="p">):&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">deal_params&lt;/span>&lt;span class="p">({&lt;/span>&lt;span class="s2">&amp;#34;name&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;秋草&amp;#34;&lt;/span>&lt;span class="p">})&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>In the common method file &lt;code>conftest.py&lt;/code>, define the fixture &lt;code>prepare&lt;/code> and set &lt;code>autouse=True&lt;/code>, which means it will be applied automatically according to the configured scope of the fixture&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;span class="lnt">3
&lt;/span>&lt;span class="lnt">4
&lt;/span>&lt;span class="lnt">5
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-python" data-lang="python">&lt;span class="line">&lt;span class="cl">&lt;span class="nd">@pytest.fixture&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">autouse&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="kc">True&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">scope&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s1">&amp;#39;function&amp;#39;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="k">def&lt;/span> &lt;span class="nf">prepare&lt;/span>&lt;span class="p">():&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nb">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s1">&amp;#39;-----some setup actions.....&amp;#39;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">yield&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nb">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s1">&amp;#39;-----some teardown actions!!&amp;#39;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>Here we set the scope of &lt;code>prepare&lt;/code> to different values respectively, and then obtain the corresponding outputs&lt;/p>
&lt;h3 id="function">function
&lt;/h3>&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;span class="lnt">12
&lt;/span>&lt;span class="lnt">13
&lt;/span>&lt;span class="lnt">14
&lt;/span>&lt;span class="lnt">15
&lt;/span>&lt;span class="lnt">16
&lt;/span>&lt;span class="lnt">17
&lt;/span>&lt;span class="lnt">18
&lt;/span>&lt;span class="lnt">19
&lt;/span>&lt;span class="lnt">20
&lt;/span>&lt;span class="lnt">21
&lt;/span>&lt;span class="lnt">22
&lt;/span>&lt;span class="lnt">23
&lt;/span>&lt;span class="lnt">24
&lt;/span>&lt;span class="lnt">25
&lt;/span>&lt;span class="lnt">26
&lt;/span>&lt;span class="lnt">27
&lt;/span>&lt;span class="lnt">28
&lt;/span>&lt;span class="lnt">29
&lt;/span>&lt;span class="lnt">30
&lt;/span>&lt;span class="lnt">31
&lt;/span>&lt;span class="lnt">32
&lt;/span>&lt;span class="lnt">33
&lt;/span>&lt;span class="lnt">34
&lt;/span>&lt;span class="lnt">35
&lt;/span>&lt;span class="lnt">36
&lt;/span>&lt;span class="lnt">37
&lt;/span>&lt;span class="lnt">38
&lt;/span>&lt;span class="lnt">39
&lt;/span>&lt;span class="lnt">40
&lt;/span>&lt;span class="lnt">41
&lt;/span>&lt;span class="lnt">42
&lt;/span>&lt;span class="lnt">43
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-console" data-lang="console">&lt;span class="line">&lt;span class="cl">&lt;span class="go">(.venv) C:\Chengxiaqiucao
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="go">pytest
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="go">======================================== test session starts =========================================
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="go">collected 8 items
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="go">&lt;/span>&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">&lt;/span>&lt;span class="go">BlogDemo/testDemo/test_ch_parm.py::test_params_mark[10] -----some setup actions.....
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="go">input :10
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="go">100
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="go">PASSED-----some teardown actions!!
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="go">&lt;/span>&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">&lt;/span>&lt;span class="go">BlogDemo/testDemo/test_ch_parm.py::test_params_mark[城下秋草] -----some setup actions.....
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="go">input :城下秋草
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="go">城下秋草城下秋草城下秋草
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="go">PASSED-----some teardown actions!!
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="go">&lt;/span>&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">&lt;/span>&lt;span class="go">BlogDemo/testDemo/test_ch_parm.py::test_params_mark[软件测试] -----some setup actions.....
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="go">input :软件测试
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="go">软件测试软件测试软件测试
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="go">PASSED-----some teardown actions!!
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="go">&lt;/span>&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">&lt;/span>&lt;span class="go">BlogDemo/testDemo/test_ch_parm.py::test_params_mark[param3] -----some setup actions.....
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="go">input :(&amp;#39;示例&amp;#39;, &amp;#39;代码&amp;#39;)
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="go">示例_代码
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="go">PASSED-----some teardown actions!!
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="go">&lt;/span>&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">&lt;/span>&lt;span class="go">BlogDemo/testDemo/test_fixture_scope.py::TestFixtureScope1::test_int -----some setup actions.....
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="go">input :2
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="go">PASSED-----some teardown actions!!
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="go">&lt;/span>&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">&lt;/span>&lt;span class="go">BlogDemo/testDemo/test_fixture_scope.py::TestFixtureScope1::test_str -----some setup actions.....
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="go">input :秋草
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="go">PASSED-----some teardown actions!!
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="go">&lt;/span>&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">&lt;/span>&lt;span class="go">BlogDemo/testDemo/test_fixture_scope.py::TestFixtureScope2::test_list -----some setup actions.....
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="go">input :[&amp;#39;城下&amp;#39;, &amp;#39;秋草&amp;#39;]
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="go">PASSED-----some teardown actions!!
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="go">&lt;/span>&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">&lt;/span>&lt;span class="go">BlogDemo/testDemo/test_fixture_scope.py::TestFixtureScope2::test_dict -----some setup actions.....
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="go">input :{&amp;#39;name&amp;#39;: &amp;#39;秋草&amp;#39;}
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="go">PASSED-----some teardown actions!!
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="go">&lt;/span>&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">&lt;/span>&lt;span class="go">========================================= 8 passed in 0.27s ==========================================
&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>The fixture ran 8 times&lt;/p>
&lt;h3 id="class">class
&lt;/h3>&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;span class="lnt">12
&lt;/span>&lt;span class="lnt">13
&lt;/span>&lt;span class="lnt">14
&lt;/span>&lt;span class="lnt">15
&lt;/span>&lt;span class="lnt">16
&lt;/span>&lt;span class="lnt">17
&lt;/span>&lt;span class="lnt">18
&lt;/span>&lt;span class="lnt">19
&lt;/span>&lt;span class="lnt">20
&lt;/span>&lt;span class="lnt">21
&lt;/span>&lt;span class="lnt">22
&lt;/span>&lt;span class="lnt">23
&lt;/span>&lt;span class="lnt">24
&lt;/span>&lt;span class="lnt">25
&lt;/span>&lt;span class="lnt">26
&lt;/span>&lt;span class="lnt">27
&lt;/span>&lt;span class="lnt">28
&lt;/span>&lt;span class="lnt">29
&lt;/span>&lt;span class="lnt">30
&lt;/span>&lt;span class="lnt">31
&lt;/span>&lt;span class="lnt">32
&lt;/span>&lt;span class="lnt">33
&lt;/span>&lt;span class="lnt">34
&lt;/span>&lt;span class="lnt">35
&lt;/span>&lt;span class="lnt">36
&lt;/span>&lt;span class="lnt">37
&lt;/span>&lt;span class="lnt">38
&lt;/span>&lt;span class="lnt">39
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-console" data-lang="console">&lt;span class="line">&lt;span class="cl">&lt;span class="go">(.venv) C:\Chengxiaqiucao
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="go">pytest
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="go">======================================== test session starts =========================================
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="go">collected 8 items
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="go">&lt;/span>&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">&lt;/span>&lt;span class="go">BlogDemo/testDemo/test_ch_parm.py::test_params_mark[10] -----some setup actions.....
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="go">input :10
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="go">100
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="go">PASSED-----some teardown actions!!
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="go">&lt;/span>&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">&lt;/span>&lt;span class="go">BlogDemo/testDemo/test_ch_parm.py::test_params_mark[城下秋草] -----some setup actions.....
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="go">input :城下秋草
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="go">城下秋草城下秋草城下秋草
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="go">PASSED-----some teardown actions!!
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="go">&lt;/span>&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">&lt;/span>&lt;span class="go">BlogDemo/testDemo/test_ch_parm.py::test_params_mark[软件测试] -----some setup actions.....
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="go">input :软件测试
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="go">软件测试软件测试软件测试
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="go">PASSED-----some teardown actions!!
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="go">&lt;/span>&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">&lt;/span>&lt;span class="go">BlogDemo/testDemo/test_ch_parm.py::test_params_mark[param3] -----some setup actions.....
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="go">input :(&amp;#39;示例&amp;#39;, &amp;#39;代码&amp;#39;)
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="go">示例_代码
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="go">PASSED-----some teardown actions!!
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="go">&lt;/span>&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">&lt;/span>&lt;span class="go">BlogDemo/testDemo/test_fixture_scope.py::TestFixtureScope1::test_int -----some setup actions.....
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="go">input :2
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="go">PASSED
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="go">BlogDemo/testDemo/test_fixture_scope.py::TestFixtureScope1::test_str input :秋草
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="go">PASSED-----some teardown actions!!
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="go">&lt;/span>&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">&lt;/span>&lt;span class="go">BlogDemo/testDemo/test_fixture_scope.py::TestFixtureScope2::test_list -----some setup actions.....
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="go">input :[&amp;#39;城下&amp;#39;, &amp;#39;秋草&amp;#39;]
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="go">PASSED
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="go">BlogDemo/testDemo/test_fixture_scope.py::TestFixtureScope2::test_dict input :{&amp;#39;name&amp;#39;: &amp;#39;秋草&amp;#39;}
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="go">PASSED-----some teardown actions!!
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="go">&lt;/span>&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">&lt;/span>&lt;span class="go">========================================= 8 passed in 0.27s ==========================================
&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>The test methods in &lt;code>test_ch_param&lt;/code>, because they are defined directly in the file, also belong to the class level, so the fixture is also called each time a parameter is assigned. In &lt;code>test_fixture_scope&lt;/code>, two test classes are explicitly defined, so it ran 2 times&lt;/p>
&lt;h3 id="module">module
&lt;/h3>&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;span class="lnt">12
&lt;/span>&lt;span class="lnt">13
&lt;/span>&lt;span class="lnt">14
&lt;/span>&lt;span class="lnt">15
&lt;/span>&lt;span class="lnt">16
&lt;/span>&lt;span class="lnt">17
&lt;/span>&lt;span class="lnt">18
&lt;/span>&lt;span class="lnt">19
&lt;/span>&lt;span class="lnt">20
&lt;/span>&lt;span class="lnt">21
&lt;/span>&lt;span class="lnt">22
&lt;/span>&lt;span class="lnt">23
&lt;/span>&lt;span class="lnt">24
&lt;/span>&lt;span class="lnt">25
&lt;/span>&lt;span class="lnt">26
&lt;/span>&lt;span class="lnt">27
&lt;/span>&lt;span class="lnt">28
&lt;/span>&lt;span class="lnt">29
&lt;/span>&lt;span class="lnt">30
&lt;/span>&lt;span class="lnt">31
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-console" data-lang="console">&lt;span class="line">&lt;span class="cl">&lt;span class="go">(.venv) C:\Chengxiaqiucao
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="go">pytest
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="go">======================================== test session starts =========================================
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="go">collected 8 items
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="go">&lt;/span>&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">&lt;/span>&lt;span class="go">BlogDemo/testDemo/test_ch_parm.py::test_params_mark[10] -----some setup actions.....
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="go">input :10
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="go">100
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="go">PASSED
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="go">BlogDemo/testDemo/test_ch_parm.py::test_params_mark[城下秋草] input :城下秋草
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="go">城下秋草城下秋草城下秋草
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="go">PASSED
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="go">BlogDemo/testDemo/test_ch_parm.py::test_params_mark[软件测试] input :软件测试
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="go">软件测试软件测试软件测试
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="go">PASSED
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="go">BlogDemo/testDemo/test_ch_parm.py::test_params_mark[param3] input :(&amp;#39;示例&amp;#39;, &amp;#39;代码&amp;#39;)
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="go">示例_代码
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="go">PASSED-----some teardown actions!!
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="go">&lt;/span>&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">&lt;/span>&lt;span class="go">BlogDemo/testDemo/test_fixture_scope.py::TestFixtureScope1::test_int -----some setup actions.....
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="go">input :2
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="go">PASSED
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="go">BlogDemo/testDemo/test_fixture_scope.py::TestFixtureScope1::test_str input :秋草
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="go">PASSED
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="go">BlogDemo/testDemo/test_fixture_scope.py::TestFixtureScope2::test_list input :[&amp;#39;城下&amp;#39;, &amp;#39;秋草&amp;#39;]
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="go">PASSED
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="go">BlogDemo/testDemo/test_fixture_scope.py::TestFixtureScope2::test_dict input :{&amp;#39;name&amp;#39;: &amp;#39;秋草&amp;#39;}
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="go">PASSED-----some teardown actions!!
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="go">&lt;/span>&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">&lt;/span>&lt;span class="go">========================================= 8 passed in 0.27s ==========================================
&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>After changing to the module scope, we can see that the fixture is called once for each module file&lt;/p>
&lt;h3 id="package">package
&lt;/h3>&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;span class="lnt">12
&lt;/span>&lt;span class="lnt">13
&lt;/span>&lt;span class="lnt">14
&lt;/span>&lt;span class="lnt">15
&lt;/span>&lt;span class="lnt">16
&lt;/span>&lt;span class="lnt">17
&lt;/span>&lt;span class="lnt">18
&lt;/span>&lt;span class="lnt">19
&lt;/span>&lt;span class="lnt">20
&lt;/span>&lt;span class="lnt">21
&lt;/span>&lt;span class="lnt">22
&lt;/span>&lt;span class="lnt">23
&lt;/span>&lt;span class="lnt">24
&lt;/span>&lt;span class="lnt">25
&lt;/span>&lt;span class="lnt">26
&lt;/span>&lt;span class="lnt">27
&lt;/span>&lt;span class="lnt">28
&lt;/span>&lt;span class="lnt">29
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-console" data-lang="console">&lt;span class="line">&lt;span class="cl">&lt;span class="go">(.venv) C:\Chengxiaqiucao
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="go">pytest
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="go">======================================== test session starts =========================================
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="go">collected 8 items
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="go">&lt;/span>&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">&lt;/span>&lt;span class="go">BlogDemo/testDemo/test_ch_parm.py::test_params_mark[10] -----some setup actions.....
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="go">input :10
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="go">100
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="go">PASSED
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="go">BlogDemo/testDemo/test_ch_parm.py::test_params_mark[城下秋草] input :城下秋草
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="go">城下秋草城下秋草城下秋草
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="go">PASSED
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="go">BlogDemo/testDemo/test_ch_parm.py::test_params_mark[软件测试] input :软件测试
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="go">软件测试软件测试软件测试
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="go">PASSED
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="go">BlogDemo/testDemo/test_ch_parm.py::test_params_mark[param3] input :(&amp;#39;示例&amp;#39;, &amp;#39;代码&amp;#39;)
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="go">示例_代码
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="go">PASSED
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="go">BlogDemo/testDemo/test_fixture_scope.py::TestFixtureScope1::test_int input :2
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="go">PASSED
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="go">BlogDemo/testDemo/test_fixture_scope.py::TestFixtureScope1::test_str input :秋草
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="go">PASSED
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="go">BlogDemo/testDemo/test_fixture_scope.py::TestFixtureScope2::test_list input :[&amp;#39;城下&amp;#39;, &amp;#39;秋草&amp;#39;]
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="go">PASSED
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="go">BlogDemo/testDemo/test_fixture_scope.py::TestFixtureScope2::test_dict input :{&amp;#39;name&amp;#39;: &amp;#39;秋草&amp;#39;}
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="go">PASSED-----some teardown actions!!
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="go">&lt;/span>&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">&lt;/span>&lt;span class="go">========================================= 8 passed in 0.27s ==========================================
&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>After changing to package, this is because the two test files are located in the same package, so it ran once&lt;/p>
&lt;h3 id="session">session
&lt;/h3>&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;span class="lnt">12
&lt;/span>&lt;span class="lnt">13
&lt;/span>&lt;span class="lnt">14
&lt;/span>&lt;span class="lnt">15
&lt;/span>&lt;span class="lnt">16
&lt;/span>&lt;span class="lnt">17
&lt;/span>&lt;span class="lnt">18
&lt;/span>&lt;span class="lnt">19
&lt;/span>&lt;span class="lnt">20
&lt;/span>&lt;span class="lnt">21
&lt;/span>&lt;span class="lnt">22
&lt;/span>&lt;span class="lnt">23
&lt;/span>&lt;span class="lnt">24
&lt;/span>&lt;span class="lnt">25
&lt;/span>&lt;span class="lnt">26
&lt;/span>&lt;span class="lnt">27
&lt;/span>&lt;span class="lnt">28
&lt;/span>&lt;span class="lnt">29
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-console" data-lang="console">&lt;span class="line">&lt;span class="cl">&lt;span class="go">(.venv) C:\Chengxiaqiucao
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="go">pytest
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="go">======================================== test session starts =========================================
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="go">collected 8 items
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="go">&lt;/span>&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">&lt;/span>&lt;span class="go">BlogDemo/testDemo/test_ch_parm.py::test_params_mark[10] -----some setup actions.....
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="go">input :10
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="go">100
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="go">PASSED
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="go">BlogDemo/testDemo/test_ch_parm.py::test_params_mark[城下秋草] input :城下秋草
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="go">城下秋草城下秋草城下秋草
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="go">PASSED
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="go">BlogDemo/testDemo/test_ch_parm.py::test_params_mark[软件测试] input :软件测试
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="go">软件测试软件测试软件测试
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="go">PASSED
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="go">BlogDemo/testDemo/test_ch_parm.py::test_params_mark[param3] input :(&amp;#39;示例&amp;#39;, &amp;#39;代码&amp;#39;)
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="go">示例_代码
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="go">PASSED
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="go">BlogDemo/testDemo/test_fixture_scope.py::TestFixtureScope1::test_int input :2
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="go">PASSED
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="go">BlogDemo/testDemo/test_fixture_scope.py::TestFixtureScope1::test_str input :秋草
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="go">PASSED
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="go">BlogDemo/testDemo/test_fixture_scope.py::TestFixtureScope2::test_list input :[&amp;#39;城下&amp;#39;, &amp;#39;秋草&amp;#39;]
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="go">PASSED
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="go">BlogDemo/testDemo/test_fixture_scope.py::TestFixtureScope2::test_dict input :{&amp;#39;name&amp;#39;: &amp;#39;秋草&amp;#39;}
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="go">PASSED-----some teardown actions!!
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="go">&lt;/span>&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">&lt;/span>&lt;span class="go">========================================= 8 passed in 0.27s ==========================================
&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>Finally, when set to session — that is, one execution session of running pytest — only then is a single fixture call triggered&lt;/p>
&lt;p>So we can see that by defining different scopes for fixtures, we can determine the scope of the fixtures we write according to our needs, which offers great flexibility&lt;/p>
&lt;h2 id="flexible-scope-definition-for-complex-fixtures">Flexible Scope Definition for Complex Fixtures
&lt;/h2>&lt;p>Sometimes in actual use — especially when the initialization work of some of our fixtures is fairly complex but may be needed at different scopes at the same time — if we had to write several different fixtures merely because of the different scopes, the code would become rather redundant. How can we handle this? In fact, we can implement it flexibly using the contextmanager context.&lt;/p>
&lt;p>For example, let us write another basic code context for a fixture:&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;span class="lnt">3
&lt;/span>&lt;span class="lnt">4
&lt;/span>&lt;span class="lnt">5
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-python" data-lang="python">&lt;span class="line">&lt;span class="cl">&lt;span class="nd">@contextmanager&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="k">def&lt;/span> &lt;span class="nf">fixture_base&lt;/span>&lt;span class="p">():&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nb">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s1">&amp;#39;~~~~~base fixture setup actions.....&amp;#39;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">yield&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nb">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s1">&amp;#39;~~~~~base fixture teardown actions!!&amp;#39;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>Then for different fixtures, we can define different fixtures according to different scopes and call the context implementation here. For example, let us define another fixture with the scope set to package&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;span class="lnt">3
&lt;/span>&lt;span class="lnt">4
&lt;/span>&lt;span class="lnt">5
&lt;/span>&lt;span class="lnt">6
&lt;/span>&lt;span class="lnt">7
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-python" data-lang="python">&lt;span class="line">&lt;span class="cl">&lt;span class="nd">@pytest.fixture&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">autouse&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="kc">False&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">scope&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s1">&amp;#39;package&amp;#39;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="k">def&lt;/span> &lt;span class="nf">fixture_module&lt;/span>&lt;span class="p">():&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;&amp;#34;&amp;#34;
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s2"> For complex fixtures where you want flexible scope handling, you can put the common code into a contextmanager,
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s2"> and then define corresponding fixtures for different scopes
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s2"> &amp;#34;&amp;#34;&amp;#34;&lt;/span> &lt;span class="k">with&lt;/span> &lt;span class="n">fixture_base&lt;/span>&lt;span class="p">()&lt;/span> &lt;span class="k">as&lt;/span> &lt;span class="n">result&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">yield&lt;/span> &lt;span class="n">result&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>👍👍This method comes from a summary by the pytest community, &lt;a class="link" href="https://github.com/pytest-dev/pytest/issues/3425" target="_blank" rel="noopener"
>original issue link&lt;/a>&lt;/p>
&lt;h2 id="execution-order-of-different-scopes">Execution Order of Different Scopes
&lt;/h2>&lt;p>In the example above we actually saw the execution effect of package and session; because the test methods are all in the same package, there is no difference in effect. But in fact, different scopes also have an execution order&lt;/p>
&lt;p>The order is summarized as follows:&lt;/p>
&lt;p>&lt;code>session&lt;/code> &amp;gt; &lt;code>package&lt;/code> &amp;gt; &lt;code>module&lt;/code> &amp;gt; &lt;code>class&lt;/code> &amp;gt; &lt;code>function&lt;/code>&lt;/p>
&lt;p>After adding up to two fixtures here, the execution result is:&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;span class="lnt">12
&lt;/span>&lt;span class="lnt">13
&lt;/span>&lt;span class="lnt">14
&lt;/span>&lt;span class="lnt">15
&lt;/span>&lt;span class="lnt">16
&lt;/span>&lt;span class="lnt">17
&lt;/span>&lt;span class="lnt">18
&lt;/span>&lt;span class="lnt">19
&lt;/span>&lt;span class="lnt">20
&lt;/span>&lt;span class="lnt">21
&lt;/span>&lt;span class="lnt">22
&lt;/span>&lt;span class="lnt">23
&lt;/span>&lt;span class="lnt">24
&lt;/span>&lt;span class="lnt">25
&lt;/span>&lt;span class="lnt">26
&lt;/span>&lt;span class="lnt">27
&lt;/span>&lt;span class="lnt">28
&lt;/span>&lt;span class="lnt">29
&lt;/span>&lt;span class="lnt">30
&lt;/span>&lt;span class="lnt">31
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-console" data-lang="console">&lt;span class="line">&lt;span class="cl">&lt;span class="go">(.venv) C:\Chengxiaqiucao
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="go">pytest
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="go">======================================== test session starts =========================================
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="go">collected 8 items
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="go">&lt;/span>&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">&lt;/span>&lt;span class="go">BlogDemo/testDemo/test_ch_parm.py::test_params_mark[10] -----some setup actions.....
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="go">~~~~~base fixture setup actions.....
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="go">input :10
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="go">100
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="go">PASSED
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="go">BlogDemo/testDemo/test_ch_parm.py::test_params_mark[城下秋草] input :城下秋草
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="go">城下秋草城下秋草城下秋草
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="go">PASSED
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="go">BlogDemo/testDemo/test_ch_parm.py::test_params_mark[软件测试] input :软件测试
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="go">软件测试软件测试软件测试
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="go">PASSED
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="go">BlogDemo/testDemo/test_ch_parm.py::test_params_mark[param3] input :(&amp;#39;示例&amp;#39;, &amp;#39;代码&amp;#39;)
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="go">示例_代码
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="go">PASSED
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="go">BlogDemo/testDemo/test_fixture_scope.py::TestFixtureScope1::test_int input :2
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="go">PASSED
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="go">BlogDemo/testDemo/test_fixture_scope.py::TestFixtureScope1::test_str input :秋草
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="go">PASSED
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="go">BlogDemo/testDemo/test_fixture_scope.py::TestFixtureScope2::test_list input :[&amp;#39;城下&amp;#39;, &amp;#39;秋草&amp;#39;]
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="go">PASSED
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="go">BlogDemo/testDemo/test_fixture_scope.py::TestFixtureScope2::test_dict input :{&amp;#39;name&amp;#39;: &amp;#39;秋草&amp;#39;}
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="go">PASSED~~~~~base fixture teardown actions!!
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="go">-----some teardown actions!!
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="go">&lt;/span>&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">&lt;/span>&lt;span class="go">========================================= 8 passed in 0.27s ==========================================
&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>We can see that &lt;code>session&lt;/code> is executed earlier than &lt;code>package&lt;/code> and is also torn down later.&lt;/p>
&lt;p>So the above is the summary of pytest scope.&lt;/p>
&lt;hr>
&lt;p>Let me also promote my testing course. Those who are interested can learn more through the link below~&lt;/p>
&lt;p>❤️❤️❤️❤️ &lt;a class="link" href="https://coding.imooc.com/class/chapter/885.html#Anchor" target="_blank" rel="noopener"
>Chengxiaqiucao&amp;rsquo;s Test Career Advancement Course&lt;/a> ❤️❤️❤️❤️&lt;/p></description></item><item><title>Parameterization with Pytest Fixtures and the Garbled Chinese Text Problem</title><link>https://chengxiaqiucao.github.io/en/post/016-pytest%E5%8F%82%E6%95%B0%E5%8C%96%E6%97%B6%E7%9A%84%E4%B8%AD%E6%96%87%E4%B9%B1%E7%A0%81%E9%97%AE%E9%A2%98/</link><pubDate>Sat, 24 Aug 2024 00:11:46 +0800</pubDate><guid>https://chengxiaqiucao.github.io/en/post/016-pytest%E5%8F%82%E6%95%B0%E5%8C%96%E6%97%B6%E7%9A%84%E4%B8%AD%E6%96%87%E4%B9%B1%E7%A0%81%E9%97%AE%E9%A2%98/</guid><description>&lt;img src="https://chengxiaqiucao.github.io/post/016-pytest%E5%8F%82%E6%95%B0%E5%8C%96%E6%97%B6%E7%9A%84%E4%B8%AD%E6%96%87%E4%B9%B1%E7%A0%81%E9%97%AE%E9%A2%98/Pasted-20240824.webp" alt="Featured image of post Parameterization with Pytest Fixtures and the Garbled Chinese Text Problem" />&lt;p>As we know, Pytest is the mainstream testing framework for Test Automation in the Python technology stack. It supports flexible test discovery and execution strategies, powerful fixtures, and a rich ecosystem of plugins.&lt;/p>
&lt;p>Besides parameterization via pytest&amp;rsquo;s &lt;code>parametrize&lt;/code> marker, we can also conveniently implement parameterized testing through the &lt;code>param&lt;/code> parameter of a fixture&lt;/p>
&lt;h2 id="implementing-parameterization-with-fixtures">Implementing Parameterization with Fixtures
&lt;/h2>&lt;p>Suppose we have the following code under test, which produces different output depending on the type of the parameter passed in&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;span class="lnt">3
&lt;/span>&lt;span class="lnt">4
&lt;/span>&lt;span class="lnt">5
&lt;/span>&lt;span class="lnt">6
&lt;/span>&lt;span class="lnt">7
&lt;/span>&lt;span class="lnt">8
&lt;/span>&lt;span class="lnt">9
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-python" data-lang="python">&lt;span class="line">&lt;span class="cl">&lt;span class="k">def&lt;/span> &lt;span class="nf">deal_params&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">p&lt;/span>&lt;span class="p">):&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">if&lt;/span> &lt;span class="nb">type&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">p&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="ow">is&lt;/span> &lt;span class="nb">int&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">return&lt;/span> &lt;span class="n">p&lt;/span>&lt;span class="o">*&lt;/span>&lt;span class="mi">10&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">if&lt;/span> &lt;span class="nb">type&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">p&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="ow">is&lt;/span> &lt;span class="nb">str&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">return&lt;/span> &lt;span class="sa">f&lt;/span>&lt;span class="s2">&amp;#34;输入了:&lt;/span>&lt;span class="si">{&lt;/span>&lt;span class="n">p&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">if&lt;/span> &lt;span class="nb">type&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">p&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="ow">in&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="nb">tuple&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="nb">list&lt;/span>&lt;span class="p">):&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">return&lt;/span> &lt;span class="s2">&amp;#34;_&amp;#34;&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">join&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">p&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">else&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">raise&lt;/span> &lt;span class="ne">TypeError&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>Then we write the corresponding test code: first we define a fixture and set the params list, then obtain each param through the fixture&amp;rsquo;s own request. For example, here we define several parameters. The Chinese strings in the example below are example parameter values. In addition, we also define the fixture&amp;rsquo;s setup and teardown actions. The test method simply calls the function under test.&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;span class="lnt">3
&lt;/span>&lt;span class="lnt">4
&lt;/span>&lt;span class="lnt">5
&lt;/span>&lt;span class="lnt">6
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-python" data-lang="python">&lt;span class="line">&lt;span class="cl">&lt;span class="nd">@pytest.fixture&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">params&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="mi">10&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="s2">&amp;#34;城下秋草&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="s2">&amp;#34;软件测试&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="s2">&amp;#34;示例&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="s2">&amp;#34;代码&amp;#34;&lt;/span>&lt;span class="p">)])&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="k">def&lt;/span> &lt;span class="nf">fix_env&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">request&lt;/span>&lt;span class="p">):&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">yield&lt;/span> &lt;span class="n">request&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">param&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="k">def&lt;/span> &lt;span class="nf">test_params&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">fix_env&lt;/span>&lt;span class="p">):&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nb">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">deal_params&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">fix_env&lt;/span>&lt;span class="p">))&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>Running it produces the following output:
&lt;img src="https://chengxiaqiucao.github.io/post/016-pytest%E5%8F%82%E6%95%B0%E5%8C%96%E6%97%B6%E7%9A%84%E4%B8%AD%E6%96%87%E4%B9%B1%E7%A0%81%E9%97%AE%E9%A2%98/Pasted-20240824_hu_3c5ea2958d1df42f.webp"
width="1024"
height="401"
srcset="https://chengxiaqiucao.github.io/post/016-pytest%E5%8F%82%E6%95%B0%E5%8C%96%E6%97%B6%E7%9A%84%E4%B8%AD%E6%96%87%E4%B9%B1%E7%A0%81%E9%97%AE%E9%A2%98/Pasted-20240824_hu_b8fd441d8a3dfdda.webp 480w, https://chengxiaqiucao.github.io/post/016-pytest%E5%8F%82%E6%95%B0%E5%8C%96%E6%97%B6%E7%9A%84%E4%B8%AD%E6%96%87%E4%B9%B1%E7%A0%81%E9%97%AE%E9%A2%98/Pasted-20240824_hu_3c5ea2958d1df42f.webp 1024w"
loading="lazy"
class="gallery-image"
data-flex-grow="255"
data-flex-basis="612px"
>
As you can see, although parameterization ran successfully, there is a problem here: in the output, the test case ID is displayed as garbled text.
According to pytest&amp;rsquo;s ID generation rules, if it is a string or a number, the parameter itself that was passed in is displayed (of course you can also use the ids parameter to reassign the corresponding ID of a parameter); if it is a tuple, list, or dict, it displays the fixture&amp;rsquo;s name plus the parameter index, such as &lt;code>fix_env3&lt;/code> here&lt;/p>
&lt;p>Here the characters are Chinese, shown as the encoding before unicode escaping, so there is still a problem with the Chinese conversion. That is to say, Pytest&amp;rsquo;s handling of fixture parameters uses ASCII encoding for display by default, whereas for Chinese we want it displayed with unicode encoding.&lt;/p>
&lt;h3 id="solution-one-for-garbled-chinese-text">Solution One for Garbled Chinese Text
&lt;/h3>&lt;p>Therefore, the first way to solve this problem here is to use Pytest&amp;rsquo;s centralized fixture configuration file &lt;code>conftest.py&lt;/code>, and within it use Pytest&amp;rsquo;s hook mechanism to modify the part of the test case collection method that generates the test case IDs. The corresponding code:&lt;/p>
&lt;p>Defined in conftest.py at the same level as the test case file:&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;span class="lnt">3
&lt;/span>&lt;span class="lnt">4
&lt;/span>&lt;span class="lnt">5
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-python" data-lang="python">&lt;span class="line">&lt;span class="cl">&lt;span class="k">def&lt;/span> &lt;span class="nf">pytest_collection_modifyitems&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">items&lt;/span>&lt;span class="p">):&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># item is a collected test case; re-encode it&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">for&lt;/span> &lt;span class="n">item&lt;/span> &lt;span class="ow">in&lt;/span> &lt;span class="n">items&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">item&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">name&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">item&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">name&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">encode&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s2">&amp;#34;utf-8&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">decode&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s2">&amp;#34;unicode-escape&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">item&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">_nodeid&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">item&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">_nodeid&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">encode&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s2">&amp;#34;utf-8&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">decode&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s2">&amp;#34;unicode-escape&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>Run it again and you can see that Chinese is now displayed correctly
&lt;img src="https://chengxiaqiucao.github.io/post/016-pytest%E5%8F%82%E6%95%B0%E5%8C%96%E6%97%B6%E7%9A%84%E4%B8%AD%E6%96%87%E4%B9%B1%E7%A0%81%E9%97%AE%E9%A2%98/Pasted-20240824-1_hu_c7286eab31fbf497.webp"
width="1024"
height="438"
srcset="https://chengxiaqiucao.github.io/post/016-pytest%E5%8F%82%E6%95%B0%E5%8C%96%E6%97%B6%E7%9A%84%E4%B8%AD%E6%96%87%E4%B9%B1%E7%A0%81%E9%97%AE%E9%A2%98/Pasted-20240824-1_hu_29a366a744446fa2.webp 480w, https://chengxiaqiucao.github.io/post/016-pytest%E5%8F%82%E6%95%B0%E5%8C%96%E6%97%B6%E7%9A%84%E4%B8%AD%E6%96%87%E4%B9%B1%E7%A0%81%E9%97%AE%E9%A2%98/Pasted-20240824-1_hu_c7286eab31fbf497.webp 1024w"
loading="lazy"
class="gallery-image"
data-flex-grow="233"
data-flex-basis="561px"
>
&lt;/p>
&lt;h3 id="solution-two-for-garbled-chinese-text">Solution Two for Garbled Chinese Text
&lt;/h3>&lt;p>Besides modifying the hook to re-encode the test case IDs, Pytest itself actually also provides a configuration parameter. It is just that this configuration is not the officially recommended solution. Under certain circumstances on some operating systems, using this configuration may cause some unusual bugs. But the author has tested it on Windows and Ubuntu without any problems.&lt;/p>
&lt;p>The corresponding configuration is:&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-ini" data-lang="ini">&lt;span class="line">&lt;span class="cl">&lt;span class="na">disable_test_id_escaping_and_forfeit_all_rights_to_community_support&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="s">True&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>As you can tell from this extremely long configuration name, it disables test ID escaping while forfeiting community support 😂😂&lt;/p>
&lt;p>Adding this configuration in pytest.ini, without using the hook above, also gives the effect of Chinese displaying correctly.&lt;/p>
&lt;hr>
&lt;p>The above are the solutions to the garbled text problem you may encounter when Chinese is displayed during parameterization in Pytest.&lt;/p>
&lt;p>My Test Career Advancement Course is currently being actively promoted on IMOOC; if you&amp;rsquo;re interested, you can learn more through the link below&lt;/p>
&lt;p>❤️❤️❤️❤️ &lt;a class="link" href="https://coding.imooc.com/class/chapter/885.html#Anchor" target="_blank" rel="noopener"
>Chengxia Qiucao&amp;rsquo;s Test Career Advancement Course&lt;/a> ❤️❤️❤️❤️&lt;/p>
&lt;hr></description></item></channel></rss>