<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>测试周刊 on 重定向学院</title><link>https://itest2025.pages.dev/tags/%E6%B5%8B%E8%AF%95%E5%91%A8%E5%88%8A/</link><description>Recent content in 测试周刊 on 重定向学院</description><generator>Hugo</generator><language>zh-CN</language><lastBuildDate>Fri, 25 Jul 2025 10:26:47 +0800</lastBuildDate><atom:link href="https://itest2025.pages.dev/tags/%E6%B5%8B%E8%AF%95%E5%91%A8%E5%88%8A/index.xml" rel="self" type="application/rss+xml"/><item><title>测试周刊008: AI 在测试中有深度的应用了?</title><link>https://itest2025.pages.dev/testing_weekly_008/</link><pubDate>Fri, 25 Jul 2025 10:26:47 +0800</pubDate><guid>https://itest2025.pages.dev/testing_weekly_008/</guid><description>&lt;p>本期内容再次印证了软件测试行业正在经历的深刻变革。从传统的手工测试向智能化测试转变，从技术层面的优化到文化层面的重塑，我们看到测试工程师们不仅要掌握新兴的 AI 工具，更需要具备战略思维和质量意识的深度转变。&lt;/p></description></item><item><title>测试周刊007: AI 测试工具2025上半年盘点</title><link>https://itest2025.pages.dev/testing_weekly_ai_testing_tools_for_2025_q2/</link><pubDate>Thu, 03 Jul 2025 16:26:47 +0800</pubDate><guid>https://itest2025.pages.dev/testing_weekly_ai_testing_tools_for_2025_q2/</guid><description>&lt;p>2025 年已经过去一半了，这半年里，ai 与测试工具的结合有了不少进展。&lt;/p>
&lt;p>今天我们就一起来盘点一下。&lt;/p></description></item><item><title>测试周刊006: playwrightv1.53的新功能</title><link>https://itest2025.pages.dev/testing_weekly_pydoll_first_impression/</link><pubDate>Thu, 26 Jun 2025 16:26:47 +0800</pubDate><guid>https://itest2025.pages.dev/testing_weekly_pydoll_first_impression/</guid><description>&lt;p>在一个已有开发节奏的团队中，作为第一位测试人员去推行新流程，绝非易事。&lt;/p>
&lt;p>你会被开发质疑：是不是要拖慢上线进度？是不是要卡死流程，让整个开发团队都不爽？&lt;/p>
&lt;p>这些成见不是你的错，但你必须面对它们。&lt;/p>
&lt;!-- more -->
&lt;h2 id="pydoll-初体验">pydoll 初体验&lt;/h2>
&lt;p>之前介绍过一款新的 ui 自动化测试工具&amp;mdash;-&lt;a href="https://autoscrape-labs.github.io/pydoll/" target="_blank" rel="noopener noreffer ">pydoll&lt;/a>。&lt;/p>
&lt;p>今天抽空在 github 的 copilot 的帮助下试用了一下。&lt;/p>
&lt;p>我用 pydoll 实现了一个测试&lt;a href="https://todomvc.com/examples/react/dist/" target="_blank" rel="noopener noreffer ">任务列表&lt;/a>的测试套件，包含 5 个测试用例。&lt;/p>
&lt;p>具体用例如下&lt;/p>
&lt;div class="highlight">&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">asyncio&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="kn">import&lt;/span> &lt;span class="nn">os&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="kn">import&lt;/span> &lt;span class="nn">unittest&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">pydoll.browser.chromium&lt;/span> &lt;span class="kn">import&lt;/span> &lt;span class="n">Chrome&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">pydoll.browser.options&lt;/span> &lt;span class="kn">import&lt;/span> &lt;span class="n">ChromiumOptions&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">pydoll.constants&lt;/span> &lt;span class="kn">import&lt;/span> &lt;span class="n">Key&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">TestTodoMVC&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">unittest&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">IsolatedAsyncioTestCase&lt;/span>&lt;span class="p">):&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">async&lt;/span> &lt;span class="k">def&lt;/span> &lt;span class="nf">asyncSetUp&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="n">options&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">ChromiumOptions&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">add_argument&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s1">&amp;#39;--start-maximized&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">options&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">add_argument&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s1">&amp;#39;--disable-notifications&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">browser&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">options&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">tab&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="k">await&lt;/span> &lt;span class="bp">self&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">start&lt;/span>&lt;span class="p">()&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">await&lt;/span> &lt;span class="bp">self&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">tab&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">go_to&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s1">&amp;#39;https://todomvc.com/examples/react/dist/&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="k">async&lt;/span> &lt;span class="k">def&lt;/span> &lt;span class="nf">asyncTearDown&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">await&lt;/span> &lt;span class="bp">self&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">browser&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="fm">__aexit__&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="kc">None&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="kc">None&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="kc">None&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">async&lt;/span> &lt;span class="k">def&lt;/span> &lt;span class="nf">test_add_todo&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="n">new_todo&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="k">await&lt;/span> &lt;span class="bp">self&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">tab&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">find&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">class_name&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s1">&amp;#39;new-todo&amp;#39;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">timeout&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="mi">5&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">raise_exc&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">await&lt;/span> &lt;span class="n">new_todo&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">type_text&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s2">&amp;#34;Install pydoll&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">await&lt;/span> &lt;span class="n">asyncio&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">sleep&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="mi">1&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">await&lt;/span> &lt;span class="n">new_todo&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">press_keyboard_key&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">Key&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">ENTER&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">todo_items&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="k">await&lt;/span> &lt;span class="bp">self&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">tab&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">find&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">class_name&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="s1">&amp;#39;view&amp;#39;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">timeout&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="mi">5&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">find_all&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">raise_exc&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">found&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="kc">False&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">texts&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="k">for&lt;/span> &lt;span class="n">item&lt;/span> &lt;span class="ow">in&lt;/span> &lt;span class="n">todo_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">text&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="k">await&lt;/span> &lt;span class="n">item&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">text&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">texts&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">append&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">text&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="s2">&amp;#34;Install pydoll&amp;#34;&lt;/span> &lt;span class="ow">in&lt;/span> &lt;span class="n">text&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">found&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="kc">True&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">break&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">assertTrue&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">found&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">async&lt;/span> &lt;span class="k">def&lt;/span> &lt;span class="nf">test_complete_todo&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">await&lt;/span> &lt;span class="bp">self&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">test_add_todo&lt;/span>&lt;span class="p">()&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">toggle&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="k">await&lt;/span> &lt;span class="bp">self&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">tab&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">find&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">class_name&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s2">&amp;#34;toggle&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">timeout&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="mi">5&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">raise_exc&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">await&lt;/span> &lt;span class="n">toggle&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">completed&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="k">await&lt;/span> &lt;span class="bp">self&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">tab&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">find&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">class_name&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s1">&amp;#39;completed&amp;#39;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">timeout&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="mi">5&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">raise_exc&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="bp">self&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">assertIsNotNone&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">completed&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">async&lt;/span> &lt;span class="k">def&lt;/span> &lt;span class="nf">test_delete_todo&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">await&lt;/span> &lt;span class="bp">self&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">test_add_todo&lt;/span>&lt;span class="p">()&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">todo_item&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="k">await&lt;/span> &lt;span class="bp">self&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">tab&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">find&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">class_name&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s1">&amp;#39;view&amp;#39;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">timeout&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="mi">5&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">raise_exc&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">await&lt;/span> &lt;span class="n">todo_item&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">destroy_btn&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="k">await&lt;/span> &lt;span class="n">todo_item&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">find&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">class_name&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s1">&amp;#39;destroy&amp;#39;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">timeout&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="mi">5&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">raise_exc&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">await&lt;/span> &lt;span class="n">destroy_btn&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">todo_items&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="k">await&lt;/span> &lt;span class="bp">self&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">tab&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">find&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">class_name&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s1">&amp;#39;view&amp;#39;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">find_all&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">found&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="kc">False&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">todo_items&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="s2">&amp;#34;Install pydoll&amp;#34;&lt;/span> &lt;span class="ow">in&lt;/span> &lt;span class="n">item&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">text&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">found&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="kc">True&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">break&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">assertFalse&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">found&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">async&lt;/span> &lt;span class="k">def&lt;/span> &lt;span class="nf">test_filter_todo&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">await&lt;/span> &lt;span class="bp">self&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">test_add_todo&lt;/span>&lt;span class="p">()&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">toggle&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="k">await&lt;/span> &lt;span class="bp">self&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">tab&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">find&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">class_name&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s2">&amp;#34;toggle&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">timeout&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="mi">5&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">raise_exc&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">await&lt;/span> &lt;span class="n">toggle&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">active_filter&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="k">await&lt;/span> &lt;span class="bp">self&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">tab&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">find&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">text&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s2">&amp;#34;Active&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">timeout&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="mi">5&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">raise_exc&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">await&lt;/span> &lt;span class="n">active_filter&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="k">await&lt;/span> &lt;span class="n">asyncio&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">sleep&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="mi">1&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">active_items&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="p">[&lt;/span>&lt;span class="n">item&lt;/span> &lt;span class="k">for&lt;/span> &lt;span class="n">item&lt;/span> &lt;span class="ow">in&lt;/span> &lt;span class="k">await&lt;/span> &lt;span class="bp">self&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">tab&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">find&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">class_name&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="s1">&amp;#39;view&amp;#39;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">find_all&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="bp">self&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">assertEqual&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="nb">len&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">active_items&lt;/span>&lt;span class="p">),&lt;/span> &lt;span class="mi">0&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_filter&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="k">await&lt;/span> &lt;span class="bp">self&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">tab&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">find&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">text&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s2">&amp;#34;Completed&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">timeout&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="mi">5&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">raise_exc&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">await&lt;/span> &lt;span class="n">completed_filter&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="k">await&lt;/span> &lt;span class="n">asyncio&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">sleep&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="mi">1&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_items&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="k">await&lt;/span> &lt;span class="bp">self&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">tab&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">find&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">class_name&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="s1">&amp;#39;view&amp;#39;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">find_all&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">found&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="kc">False&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">completed_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">title&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="k">await&lt;/span> &lt;span class="n">item&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">text&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">if&lt;/span> &lt;span class="s2">&amp;#34;Install pydoll&amp;#34;&lt;/span> &lt;span class="ow">in&lt;/span> &lt;span class="n">title&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">found&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="kc">True&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">break&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">assertTrue&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">found&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">async&lt;/span> &lt;span class="k">def&lt;/span> &lt;span class="nf">test_screenshot&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">await&lt;/span> &lt;span class="bp">self&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">test_add_todo&lt;/span>&lt;span class="p">()&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">screenshot_path&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">os&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">join&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">os&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">getcwd&lt;/span>&lt;span class="p">(),&lt;/span> &lt;span class="s1">&amp;#39;pydoll_repo.png&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">await&lt;/span> &lt;span class="bp">self&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">tab&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">take_screenshot&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">path&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="n">screenshot_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">assertTrue&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">os&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">exists&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">screenshot_path&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">if&lt;/span> &lt;span class="vm">__name__&lt;/span> &lt;span class="o">==&lt;/span> &lt;span class="s2">&amp;#34;__main__&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">unittest&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">main&lt;/span>&lt;span class="p">()&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>上面的代码实现了&lt;/p></description></item><item><title>测试周刊005: Google是怎么做测试的</title><link>https://itest2025.pages.dev/testing_weekly_how_google_do_test/</link><pubDate>Thu, 19 Jun 2025 10:12:22 +0800</pubDate><guid>https://itest2025.pages.dev/testing_weekly_how_google_do_test/</guid><description>&lt;p>在 Google 早期，测试并不是首要任务。公司文化高度依赖工程师的才华——聪明的人写聪明的代码。大多数情况下，这种方式都很有效。少数系统部署了集成测试，但广泛的、结构化的测试极其罕见。这就像软件开发的&amp;quot;狂野西部&amp;quot;时代。&lt;/p></description></item><item><title>测试周刊004: 单元测试和接口测试用例将成为标配</title><link>https://itest2025.pages.dev/weekly_report_20250530/</link><pubDate>Fri, 30 May 2025 09:26:37 +0800</pubDate><guid>https://itest2025.pages.dev/weekly_report_20250530/</guid><description>&lt;p>马上就到端午假期了。&lt;/p>
&lt;p>今天在电梯听到两位女士的对话，大概的意思是一位认为只有一天的假期有点不太过瘾，而另一位觉得假期归来以后上 4 休 2 已经是非常划算了。&lt;/p>
&lt;p>反正我是同意后者的。&lt;/p>
&lt;p>&lt;img
 class="lazyload"
 src="https://itest2025.pages.dev/svg/loading.min.svg"
 data-src="https://images.unsplash.com/photo-1749984340771-c3a967db0a28?q=80&amp;amp;w=2066&amp;amp;auto=format&amp;amp;fit=crop&amp;amp;ixlib=rb-4.1.0&amp;amp;ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D"
 data-srcset="https://images.unsplash.com/photo-1749984340771-c3a967db0a28?q=80&amp;amp;w=2066&amp;amp;auto=format&amp;amp;fit=crop&amp;amp;ixlib=rb-4.1.0&amp;amp;ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D, https://images.unsplash.com/photo-1749984340771-c3a967db0a28?q=80&amp;amp;w=2066&amp;amp;auto=format&amp;amp;fit=crop&amp;amp;ixlib=rb-4.1.0&amp;amp;ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D 1.5x, https://images.unsplash.com/photo-1749984340771-c3a967db0a28?q=80&amp;amp;w=2066&amp;amp;auto=format&amp;amp;fit=crop&amp;amp;ixlib=rb-4.1.0&amp;amp;ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D 2x"
 data-sizes="auto"
 alt="https://images.unsplash.com/photo-1749984340771-c3a967db0a28?q=80&amp;amp;w=2066&amp;amp;auto=format&amp;amp;fit=crop&amp;amp;ixlib=rb-4.1.0&amp;amp;ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D"
 title="https://images.unsplash.com/photo-1749984340771-c3a967db0a28?q=80&amp;amp;w=2066&amp;amp;auto=format&amp;amp;fit=crop&amp;amp;ixlib=rb-4.1.0&amp;amp;ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D" />&lt;/p>
&lt;h2 id="观点">观点&lt;/h2>
&lt;h3 id="ai-将使得单元测试和接口测试成为标配">AI 将使得单元测试和接口测试成为标配&lt;/h3>
&lt;p>前些天 deepseek 发布了新模型，该模型在代码能力上有了较大的提升。&lt;/p>
&lt;p>有人尝试之后表示模型不仅可以正确实现编码需求，还可以在生成代码的同时给出完整的单元测试用例。&lt;/p>
&lt;p>今后将有越来越多的代码会由 ai 实现，而我们可以非常自信的要求 ai 在给出实现的同时，给出完成的单元测试用例和接口测试用例。&lt;/p>
&lt;p>因此在不久的将来，单元测试用例和接口测试用例将会成为增量代码的标配了吧。&lt;/p>
&lt;p>测试同学可能不需要人人都会写单元测试用例了，但是学会看懂测试用例，并用测试思维来对用例进行评审，反而是更实用的技能了。&lt;/p>
&lt;h3 id="从质量保证到集成保证">从质量保证到集成保证&lt;/h3>
&lt;p>&lt;a href="https://medium.com/@sean.zhang/lets-rethink-the-role-of-qa-it-s-not-about-owning-quality-ed159d0a424b" target="_blank" rel="noopener noreffer ">https://medium.com/@sean.zhang/lets-rethink-the-role-of-qa-it-s-not-about-owning-quality-ed159d0a424b&lt;/a>&lt;/p>
&lt;p>传统的&amp;quot;质量保证&amp;quot;概念存在两个极端问题：&lt;/p>
&lt;ul>
&lt;li>过度依赖 QA：认为 QA 团队独自负责产品质量，其他团队可以推卸责任&lt;/li>
&lt;li>完全取消 QA：认为每个工程师都应该&amp;quot;拥有质量&amp;quot;，但缺乏系统级验证&lt;/li>
&lt;/ul>
&lt;p>作者认为传统的&amp;quot;质量保证&amp;quot;（QA）概念存在误导性，因为质量应该是每个团队的共同责任，而不是 QA 部门的专属职责。&lt;/p>
&lt;p>他提出将 QA 重新定义为&amp;quot;集成保证&amp;quot;（Integration Assurance），专注于验证现代软件系统中多个服务和组件之间的协同工作，就像苹果公司需要确保 iPhone 各个供应商的零件能完美集成一样。&lt;/p>
&lt;p>这个角色类似足球比赛中的守门员——不是唯一的防线，但是防止问题到达用户的最后屏障，同时帮助发现系统级的协调问题和集成风险，而 AI 测试工具应该主要由这个集成保证团队来使用，以确保从全局视角进行有效的端到端验证。&lt;/p>
&lt;h2 id="自动化测试">自动化测试&lt;/h2>
&lt;h3 id="有效的软件测试需要通过测试替身test-doubles来隔离被测系统从而编写可控可靠的单元测试">有效的软件测试需要通过测试替身（Test Doubles）来隔离被测系统，从而编写可控、可靠的单元测试&lt;/h3>
&lt;p>&lt;a href="https://medium.com/@raissa.puti/behind-the-green-check-a-guide-to-test-doubles-7199be3b08c2" target="_blank" rel="noopener noreffer ">https://medium.com/@raissa.puti/behind-the-green-check-a-guide-to-test-doubles-7199be3b08c2&lt;/a>&lt;/p>
&lt;p>作者认为，真正的测试不仅仅是检查功能是否正常运行，而是要通过 Dummy、Stub、Spy、Mock、Fake 等不同类型的测试替身来替代真实的外部依赖（如 API、数据库、时间服务等），这样可以：&lt;/p>
&lt;ul>
&lt;li>控制测试环境和输入数据，&lt;/li>
&lt;li>验证特定的交互行为，&lt;/li>
&lt;li>避免依赖不稳定的外部服务&lt;/li>
&lt;li>提高测试速度和可靠性。&lt;/li>
&lt;/ul>
&lt;p>作者以自己的 React 项目 SiNgawas 为例，展示了如何在前端测试中应用这些概念，同时分享了借助 AI 工具来改进测试设计的经验。文章强调，好的测试应该专注于验证有意义的行为，而不是简单地检查 UI 渲染，通过合理使用测试替身可以让每个测试都有明确的目的和可预测的结果。&lt;/p></description></item><item><title>测试周刊003: 大模型时代测试将会变得更加重要</title><link>https://itest2025.pages.dev/weekly_report_20250509/</link><pubDate>Fri, 09 May 2025 09:36:02 +0800</pubDate><guid>https://itest2025.pages.dev/weekly_report_20250509/</guid><description>&lt;p>五一假期结束了。&lt;/p>
&lt;p>这次五一完美的错峰出行。&lt;/p>
&lt;p>核心的原因是起的早。&lt;/p>
&lt;p>天刚亮就出发，第一波到达景区，人流汹涌的时候就回酒店休息。&lt;/p>
&lt;p>世间的喧闹与我无关。&lt;/p>
&lt;p>这大概是一种错位竞争吧。&lt;/p>
&lt;p>比如，当测试都在千军万马涌入新领域的时候，业务在原有的业务上进行深耕反而会取得一些错位竞争的优势。&lt;/p>
&lt;p>&lt;img
 class="lazyload"
 src="https://itest2025.pages.dev/svg/loading.min.svg"
 data-src="https://images.unsplash.com/photo-1592636120953-3d2b28ebfd69?q=80&amp;amp;w=2071&amp;amp;auto=format&amp;amp;fit=crop&amp;amp;ixlib=rb-4.1.0&amp;amp;ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D"
 data-srcset="https://images.unsplash.com/photo-1592636120953-3d2b28ebfd69?q=80&amp;amp;w=2071&amp;amp;auto=format&amp;amp;fit=crop&amp;amp;ixlib=rb-4.1.0&amp;amp;ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D, https://images.unsplash.com/photo-1592636120953-3d2b28ebfd69?q=80&amp;amp;w=2071&amp;amp;auto=format&amp;amp;fit=crop&amp;amp;ixlib=rb-4.1.0&amp;amp;ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D 1.5x, https://images.unsplash.com/photo-1592636120953-3d2b28ebfd69?q=80&amp;amp;w=2071&amp;amp;auto=format&amp;amp;fit=crop&amp;amp;ixlib=rb-4.1.0&amp;amp;ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D 2x"
 data-sizes="auto"
 alt="https://images.unsplash.com/photo-1592636120953-3d2b28ebfd69?q=80&amp;amp;w=2071&amp;amp;auto=format&amp;amp;fit=crop&amp;amp;ixlib=rb-4.1.0&amp;amp;ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D"
 title="https://images.unsplash.com/photo-1592636120953-3d2b28ebfd69?q=80&amp;amp;w=2071&amp;amp;auto=format&amp;amp;fit=crop&amp;amp;ixlib=rb-4.1.0&amp;amp;ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D" />&lt;/p>
&lt;h2 id="观点">观点&lt;/h2>
&lt;h3 id="测试将会变得越来越重要">测试将会变得越来越重要&lt;/h3>
&lt;p>&lt;a href="https://filiphric.com/testing-will-become-more-important-not-less" target="_blank" rel="noopener noreffer ">https://filiphric.com/testing-will-become-more-important-not-less&lt;/a>&lt;/p>
&lt;p>作者认为在 LLM 时代，测试将会变得举足轻重，并给出了几个预测。&lt;/p>
&lt;ol>
&lt;li>测试将更紧密嵌入软件创建过程&lt;/li>
&lt;/ol>
&lt;ul>
&lt;li>AI 不仅生成应用代码，还将同时生成测试代码&lt;/li>
&lt;li>code review 时也将包括 review 通过的测试&lt;/li>
&lt;li>运行先前迭代生成的测试可避免回归问题&lt;/li>
&lt;/ul>
&lt;ol start="2">
&lt;li>更多 AI 解决方案将整合自动化测试&lt;/li>
&lt;/ol>
&lt;ul>
&lt;li>将出现更多能同时生成代码和测试的 AI 工具&lt;/li>
&lt;li>已有工具（如 Replay.io 的 Nut.new）能在后台运行测试并将结果反馈给 LLM&lt;/li>
&lt;/ul>
&lt;ol start="3">
&lt;li>人工测试将演变而非消失&lt;/li>
&lt;/ol>
&lt;ul>
&lt;li>人工测试将更加精细，专注于新功能测试和 code review&lt;/li>
&lt;li>回归测试将主要由自动化测试承担&lt;/li>
&lt;li>测试人员将专注于变更测试，而不是专门写自动化测试用例&lt;/li>
&lt;/ul>
&lt;ol start="4">
&lt;li>良好的测试设计将继续受到高度重视&lt;/li>
&lt;/ol>
&lt;ul>
&lt;li>优秀测试工程师的价值不仅在于编写测试代码&lt;/li>
&lt;li>良好的测试实践、测试数据架构和风险区域识别能力更为关键&lt;/li>
&lt;li>技术精湛的测试人员将引导和 review AI 生成的测试代码&lt;/li>
&lt;/ul>
&lt;ol start="5">
&lt;li>应用和测试运行时将成为巨大挑战&lt;/li>
&lt;/ol>
&lt;ul>
&lt;li>虽然 Playwright 等工具中的追踪查看功能成为标准，但应用运行时信息仍然缺乏&lt;/li>
&lt;li>AI 模型在调试软件方面仍有困难，因为它们缺乏代码实际运行方式的信息&lt;/li>
&lt;li>可观察性工具可能是让 AI 生成可靠代码的关键&lt;/li>
&lt;/ul>
&lt;h3 id="优秀的测试工程师应该具备哪些思维方式">优秀的测试工程师应该具备哪些思维方式&lt;/h3>
&lt;p>&lt;a href="https://qualityeng.substack.com/p/the-three-mindsets-of-a-qe" target="_blank" rel="noopener noreffer ">https://qualityeng.substack.com/p/the-three-mindsets-of-a-qe&lt;/a>&lt;/p></description></item><item><title>测试周刊-AI不应该用来解决本来就不存在的问题</title><link>https://itest2025.pages.dev/ai_helps_automation_weekly_report_20250418/</link><pubDate>Thu, 17 Apr 2025 16:05:24 +0800</pubDate><guid>https://itest2025.pages.dev/ai_helps_automation_weekly_report_20250418/</guid><description>&lt;p>离五一只有两周了。&lt;/p>
&lt;p>最近有朋友买了 cursor 的会员，我驻足观看了一番。&lt;/p>
&lt;p>他先描述需求，然后让大模型生成原型，接着又让 LLM 根据原型来生成前后端项目的代码。&lt;/p>
&lt;p>整体流程一气呵成，看着非常有科幻感。&lt;/p>
&lt;p>不难想象，接下来根据可以工作的前后端代码就可以让大模型来生成 ui 和接口的自动化测试用例。&lt;/p>
&lt;p>不久的将来，通过 AI 生成的各种测试代码可能会是开发标准输出的一部分了吧。&lt;/p>
&lt;p>&lt;img
 class="lazyload"
 src="https://itest2025.pages.dev/svg/loading.min.svg"
 data-src="https://images.unsplash.com/photo-1749627995669-4d4dda3a9c1d?q=80&amp;amp;w=2071&amp;amp;auto=format&amp;amp;fit=crop&amp;amp;ixlib=rb-4.1.0&amp;amp;ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D"
 data-srcset="https://images.unsplash.com/photo-1749627995669-4d4dda3a9c1d?q=80&amp;amp;w=2071&amp;amp;auto=format&amp;amp;fit=crop&amp;amp;ixlib=rb-4.1.0&amp;amp;ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D, https://images.unsplash.com/photo-1749627995669-4d4dda3a9c1d?q=80&amp;amp;w=2071&amp;amp;auto=format&amp;amp;fit=crop&amp;amp;ixlib=rb-4.1.0&amp;amp;ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D 1.5x, https://images.unsplash.com/photo-1749627995669-4d4dda3a9c1d?q=80&amp;amp;w=2071&amp;amp;auto=format&amp;amp;fit=crop&amp;amp;ixlib=rb-4.1.0&amp;amp;ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D 2x"
 data-sizes="auto"
 alt="https://images.unsplash.com/photo-1749627995669-4d4dda3a9c1d?q=80&amp;amp;w=2071&amp;amp;auto=format&amp;amp;fit=crop&amp;amp;ixlib=rb-4.1.0&amp;amp;ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D"
 title="https://images.unsplash.com/photo-1749627995669-4d4dda3a9c1d?q=80&amp;amp;w=2071&amp;amp;auto=format&amp;amp;fit=crop&amp;amp;ixlib=rb-4.1.0&amp;amp;ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D" />&lt;/p>
&lt;h2 id="ai-与测试的思考">AI 与测试的思考&lt;/h2>
&lt;h3 id="停止过度设计为什么测试-id-比人工智能驱动的定位器智能更适合-ui-自动化英文">停止过度设计：为什么测试 ID 比人工智能驱动的定位器智能更适合 UI 自动化(英文)&lt;/h3>
&lt;p>&lt;a href="https://testersdigest.blogspot.com/2025/04/stop-overengineering-why-test-ids-beat.html" target="_blank" rel="noopener noreffer ">https://testersdigest.blogspot.com/2025/04/stop-overengineering-why-test-ids-beat.html&lt;/a>&lt;/p>
&lt;p>并不是所有的测试人员都关注 AI。&lt;/p>
&lt;p>并不是所有关注 AI 的测试工程师都盲目的拥抱 AI。&lt;/p>
&lt;p>这篇文章就反对使用人工智能来解决 UI 自动化测试中的定位问题，而是提倡使用测试 ID（Test IDs）这一更简单有效的方法。&lt;/p>
&lt;ol>
&lt;li>
&lt;p>&lt;strong>测试 ID 稳定可靠&lt;/strong>：测试 ID（如&lt;code>data-testid=&amp;quot;submit-button&amp;quot;&lt;/code>）是可预测的，不会因为开发人员更改 CSS 类、更新布局或重命名元素而失效。&lt;/p>
&lt;/li>
&lt;li>
&lt;p>&lt;strong>避免不必要的 AI 复杂性&lt;/strong>：为什么要让 AI 去&amp;quot;猜测&amp;quot;正确的元素，当我们可以从一开始就通过测试 ID 明确告诉 DOM 要查找什么。AI 应该增强测试策略，而不是清理本可避免的混乱。&lt;/p>
&lt;/li>
&lt;li>
&lt;p>&lt;strong>效率优于优雅&lt;/strong>：在测试中，我们的目标是验证功能而非创造艺术。Test ID 是低耦合、高效率的工具，能直接指向我们关心的元素，且运行更快。&lt;/p>
&lt;/li>
&lt;li>
&lt;p>&lt;strong>过度工程化难以扩展&lt;/strong>：使用 AI 来修复不稳定的测试和适应 UI 变化增加了另一层复杂性，意味着更多不可控的点。如果 AI 模型抽风了，不仅测试会失败，还需要进行 AI 调试。&lt;/p></description></item><item><title>测试周刊-憧憬五一的第一周</title><link>https://itest2025.pages.dev/heading_to_labours_day_weekly_report_20250411/</link><pubDate>Fri, 11 Apr 2025 09:16:18 +0800</pubDate><guid>https://itest2025.pages.dev/heading_to_labours_day_weekly_report_20250411/</guid><description>&lt;p>清明过后似乎会更加期待劳动节一些。&lt;/p>
&lt;p>今年五一放五天假，时间是充裕的，但想到各大景点的人山人海，可能最终还是会选择躲在家里吧。&lt;/p>
&lt;p>看看书，在附近活动活动，陪陪家人，安静的时光就足够了吧。&lt;/p>
&lt;h2 id="ai-工具">AI 工具&lt;/h2>
&lt;p>最近在读一本关于二战时期太平洋战争的书，里面一些细节很有意思。&lt;/p>
&lt;p>比如美军在珍珠港被空袭之后大概一年的时间里，一直在边打仗边学习。&lt;/p>
&lt;p>因为美军中大部分将军和士兵都没有经历过真正的战争。&lt;/p>
&lt;p>因此战争初期配合失误和自身混乱的情况时有发生。&lt;/p>
&lt;p>感觉跟最近的 AI 热潮很像，大部分人都没有既往的经验，只能边用边学。&lt;/p>
&lt;p>在实战中创新。&lt;/p>
&lt;p>这两周跟 AI 相关的测试动态里，最让人眼前一亮的就是 playwright 发布了官方的 MCP 支持。&lt;/p>
&lt;p>github 地址在这里:https://github.com/microsoft/playwright-mcp。&lt;/p>
&lt;p>目前 7k+的 star，热度还是很高的。&lt;/p>
&lt;p>看一下官方介绍。&lt;/p>
&lt;p>基于 Playwright 实现浏览器自动化的 MCP。该服务器使大语言模型(LLM)能够通过结构化的可访问性快照与网页交互，无需依赖截图或视觉模型。&lt;/p>
&lt;p>核心优势&lt;/p>
&lt;p>​- 快速轻量 ​​：采用 Playwright 的无障碍访问树技术，非像素级输入
​- 适配 LLM​​：无需视觉模型，完全基于结构化数据操作&lt;/p>
&lt;ul>
&lt;li>确定性操作 ​​：避免基于截图方法常见的歧义问题&lt;/li>
&lt;/ul>
&lt;p>应用场景&lt;/p>
&lt;ul>
&lt;li>网页导航与表单填写(自动化操作)&lt;/li>
&lt;li>结构化内容数据提取(爬虫)&lt;/li>
&lt;li>LLM 驱动的自动化测试(自动化测试)&lt;/li>
&lt;li>智能体的通用浏览器交互接口(通用操作)&lt;/li>
&lt;/ul>
&lt;p>既然做 UI 自动化又难又花时间，那么不如让大语言模型帮助我们去实现吧。&lt;/p>
&lt;p>目前已经看到有人使用 Playwright + Cursor + MCP Server 跑通了自动化测试的流程。&lt;/p>
&lt;p>具体效果在这里：https://www.youtube.com/watch?v=cNh3_r6UjKk&lt;/p>
&lt;h2 id="ai-测试策略">AI 测试策略&lt;/h2>
&lt;p>&lt;a href="https://testingtitbits.com/ai-usage-for-testers-quadrants-model/" target="_blank" rel="noopener noreffer ">https://testingtitbits.com/ai-usage-for-testers-quadrants-model/&lt;/a> 这篇文章里作者讨论了 AI 的测试策略。&lt;/p>
&lt;p>作者把测试工作分成了 4 个象限。&lt;/p></description></item></channel></rss>