• [技术干货] 自动化测试工具推荐
    前言我们都希望为我们的 Web 应用程序构建易维护的测试。作为这个目标的一部分,我们都希望能集中精力在测试本身,而尽量避免困在实施的具体细节中。从长远来看,测试应该是可维护的,对软件定期的变更并不会破坏测试本身或者让团队的开发节奏变慢。某些测试工具可以在做出更改和查看结果之间提供简短的反馈循环,但不能精确地模仿浏览器的行为。其他工具可能会使用实际的浏览器环境,但会降低迭代速度,并且在连续集成系统中可能会变得更加脆弱。1. Selenium知名的浏览器 web 应用测试框架,可以用 Java、C#、Ruby、JavaScript、R 和 Python 等多种编程语言编写测试案例。Selenium为每种语言提供客户端 API。Selenium WebDriver 尽可能使用原生操作系统级别的功能,而非基于浏览器 JavaScript 的命令来驱动浏览器。这样就绕过了原生功能和 JavaScript 命令之间由于细微差别而产生的问题(包括安全限制)。它提供了很大的灵活性,甚至还支持 iframe 和多个浏览器标签。卓越的跨浏览器功能令人印象深刻。可以在主流浏览器(Chrome、Firefox、Safari、Edge、Internet Explorer)上执行 Selenium 测试。Selenium Grid 可以与 WebDriver 一起使用,以在远程系统上执行测试。使用 Selenium 的唯一缺点是,它需要大量的技能,并且编写测试非常耗时。对没有编程经验的人来说,乍一看用 Selenium 编写测试似乎很容易;但是如果没有最佳实践,将导致项目内的测试自动化框架难以维护且不够稳定可靠。2. EndtestEndtest是智能自动化测试解决方案,它使用多个开源和闭源组件去简化创建和执行测试的流程。其中之一就是 Recorder 组件可以让用户不用编程技巧就能创建和执行测试。你可以用图形化界面编辑管理自己的测试案例,而不用编写任何代码。它和 Selenium 一样拥有灵活性,允许你自动化测试场景,其中包含 iframe、多个浏览器标签、文件上传、ShadowDOM, 等等。它同 Selenium 一样拥有跨浏览器的特性, 支持所有主流的浏览器(Chrome、Firefox、Safari、Edge、Internet Explorer)。同时,它也包括跨浏览器的云框架,支持 Windows、Mac 以及移动设备上的浏览器。此外,它还有支持 JavaScripts 执行的组件,以及发送 API 请求和连接数据库执行 SQL 语句的组件。这些组件可用于在测试中添加额外的验证步骤,并可准备或清理测试环境。3. WatirWatir是一个 Ruby 的浏览器自动化测试开源库。Watir 与对浏览器的互动方式和人类是一样的:如点击一个网页元素,填输入字符。它的底层使用了 Selenium 并且提供同样的灵活性,也支持跨浏览器。同时,它也支持 iframes 以及多个浏览器标签。Watir 最大的优点是 API 很容易使用,它在繁复的 Selenium API 之上增加了一层简单性。不过,它的主要缺点是,它不如 Selenium 受欢迎,在寻找答案和解决方案方面你会遇到一些困难。4. Puppeteer一个 Node 库,它提供了高级的 API 并通过 DevTools 协议来控制 Chrome(或 Chromium)。我认为未来它可以代替 Selenium。它也具有支持 iframe 和多个浏览器标签的灵活性。值得一提的是,它有 2 种不同的软件包:puppeteer-core 和 puppeteer唯一的区别是 puppeteer-core 在安装后不会自动下载 Chromium。puppeteer的主要缺点是缺乏跨浏览器功能,因为它仅适用于基于 Chromium 的浏览器。即使 Opera 和 Edge 迁移到 Chromium,也无法保证 Firefox 和 Safari 将来也会这样做。另一个缺点是,唯一受支持的语言是 Node.js。即使到 2020 年一切似乎都围绕 JS 展开,但是仍然有一些用户可能想使用其他语言进行自动化测试的开发。5. Playwright一个 Node 库,可通过单个 API 在 Chromium、Firefox 和 WebKit 浏览器上执行自动化测试。Playwright旨在不断增长的 Web 浏览器集上实现自动化操作。Playwright 类似于 Puppeteer。它支持多页面、多域名和 iframes 测试,还可以模拟移动端设备,地理指向和权限控制也是可以测试的。即使它具有更广泛的跨浏览器支持,但它也不支持 Internet Explorer。因为它是一个相对较新的库,所以你可能现在在线上找不到很多资源。如果你在编写 Node.js 代码方面有扎实的经验,那么 Playwright 可以一试。6. Sikuli在运行 Windows、Mac 或 Linux 的台式计算机屏幕上看到的任何内容,都可以使用 Sikuli 执行自动化测试。它使用由 OpenCV 支持的图像识别来识别视觉组件。如果无法轻松访问 GUI 内部或要操作的应用程序或网页的源代码,这个工具会非常方便。实际上,这是大多数现代 RPA 解决方案背后的技术。Sikuli的优点是,元素具有唯一属性或属性是否更改都无关紧要,因为 Sikuli 仅依赖于视觉识别。它的主要缺点是视觉容忍度让用户很难在不同的浏览器和屏幕尺寸之间实现自动化。并且,使用 Sikuli 库需要编程技巧,并且你可以在 Python、Ruby 和 Java 之间选择。如果你有涉及 Web 应用程序和桌面应用程序的混合自动化测试,则较好的做法是将 Selenium 用于 Web 组件,将 Sikuli 用于桌面组件。7. Micro Focus UFT (QTP)专有解决方案,以前称为 QuickTest Professional(QTP)。它提供了使 Web 应用程序和桌面应用程序自动化的功能。它使用 Visual Basic 脚本语言来定位应用程序中的元素并与之交互。同时,它还提供了一个 IDE,你只需在 GUI 中创建一个流程即可在不编写任何代码的情况下构建测试。该工具已经存在很长时间,并且确实使 Selenium 失去了很多市场份额。8. IBM Rational Functional Tester一个提供功能、回归、GUI 和数据驱动测试的自动化测试的专业工具。它确实包括有限的跨浏览器功能,因为它仅适用于 Chrome、Firefox 和 Internet Explorer。主要优点是它还可用于自动化桌面应用程序。优势之一是它具有 Eclipse Java Developer Toolkit 编辑器,这让你的团队可以轻松地使用 Eclipse 在 Java 中编写测试脚本。自带的 IDE 工具箱编辑器包含以下功能,如代码自动完成和高级调试选项。将IBM Rational Functional Tester与 CI/CD 系统集成可能会很困难,因为它被设计用在你自己的工作站上9. JestJest是一个 JavaScript 框架,允许你通过 jsdom 访问 DOM。值得一提的是,jsdom 只是浏览器工作方式的一个近似值,用于 React 应用程序的测试框架,但不是跨浏览器测试的可靠选择。Jest 确实提供了良好的迭代速度,并且具有强大的功能,例如模拟模块和计时器。理想情况下,开发人员应使用它来测试某些组件,但结果不能保证该应用程序在实际的浏览器中可以正常工作。10. CucumberCucumber是一个开源的行为驱动测试工具,支持多种编程语言,包括 Ruby,Java,Scala 和 Groovy。创建测试案例需要编程技术。实际功能可以通过使用 Gherkin 来调用。使用 Cucumber 的明显优势是,非技术用户可以轻松理解这些方案。可以说 Cucumber 并不是 Selenium 的替代品,而仅仅是对 Selenium 进行了一层包装。Selenium 和 Cucumber 的组合可提高代码的可读性,并使其更易于重用组件。
  • [问题求助] 桌面应用打不开
    使用鼠标双击打开桌面应用程序,显示执行成功但是应用没有打开。换了点击图片也显示屏幕不匹配,请问怎么可以实现打开桌面应用呢
  • [技术干货] 五大自动化测试的Python框架【转】
    自2018年被评选为编程语言以来,Python在各大排行榜上一直都是名列前茅。目前,它在Tiobe指数中排名第三个,仅次于Java和C。随着该编程语言的广泛使用,基于Python的自动化测试框架也应运而生,且不断发展与丰富。因此,开发与测试人员在为手头的项目选择测试框架时,需要考虑许多方面的因素,其中包括:框架的脚本质量,测试用例的简单性,以及运行模块可能存在的技术弱点。为了避免出现“选择困难症”,我在此为大家准备了五种Python类型的自动化测试框架,以供比较和讨论。1.Robot Framework作为最重要的Python测试框架之一,Robot Framework主要被用在测试驱动(test-driven)类型的开发与验收中。虽然是由Python开发而来,但是它也可以在基于.Net的IronPython和基于Java的Jython上运行。同时,作为一个Python框架,Robot还能够兼容诸如Windows、MacOS、以及Linux等平台。使用先决条件在使用Robot Framework(RF)之前,您需要先安装Python 2.7.14及以上的版本。我推荐您使用Python 3.6.4,以确保适当的注释能够被添加到代码段中,并能够跟踪程序的更改。同时,您还需要安装Python包管理器--pip。当然,您也必须下载相应的开发框架,例如:在开发者圈子里比较流行的PyCharm社区版。另外,由于其代码段本身并不依赖于任何IDE,因此您完全可以沿用手头既有的IDE工具。优点通过使用关键字驱动测试(keyword-driven-test)的方法,它能够帮助测试人员轻松地创建具有可读性的测试用例,进而简化了整个自动化的过程。用户能够轻松地测试数据中的语法。因为是由各种通用工具和测试库所组成,所以它不但拥有庞大的生态系统,而且可以在单独的项目中使用其各个元素。由于拥有许多类型的API,因此该框架具有高度的可扩展性。虽然并非内置功能,但是Robot可以通过Selenium Grid(请参见https://www.lambdatest.com/blog/lambdatest-now-live-with-an-online-selenium-grid-for-automated-cross-browser-testing/),来帮助用户运行各种并行测试。缺点虽然有着上述各种便利,但是Robot Framework在创建自定义的HTML报告方面比较繁琐。您顶多能用它来生成xUnit格式的简短报告。另外,Robot Framework在并行测试方面也并不见长。Robot的特点与竞品比较由于Robot具有丰富的内置库,并能使用更为简单的面向测试的DSL(Domain Specific Language),因此如果您是自动化测试领域的新手,并且缺乏开发经验的话,那么将它作为Python测试框架要比下面将要提到的Pytest或Pyunit,更容易上手一些。当然,如果您需要开发复杂的自动化框架,那么还请使用Pytest、或其他类型的Python框架。2.Pytest适用于多种软件测试的Pytest,是另一个Python类型的自动化测试框架。凭借着其开源和易学的特点,该工具经常被QA(质量分析)团队、开发团队、个人团队、以及各种开源项目所使用。鉴于Pytest具有“断言重写(assert rewriting)”之类的实用功能,许多大型互联网应用,如Dropbox和Mozilla,都已经从下面将要提到的unittest(Pyunit)切换到了Pytest之上。使用先决条件除了基本的Python知识,用户并不需要更多的技术储备。另外,用户只需要有一台带有命令行界面的测试设备,并且安装好了Python包管理器、以及可用于开发的IDE工具。优点过去,开发人员必须将他们的测试包含在各种大型的类中。如今,Pytest可以让用户写出更为紧凑的测试套件。其他的测试工具会要求开发或测试人员使用调试器,或以日志检查的方式检测某个特定值的来源。而用户在用Pytest来编写测试用例时,完全可以将所有的值都存储在测试用例之中,直到再获悉有哪些值失败了、以及哪些值得到了断言。由于涉及到的样板代码(boilerplate code)并不多,因此用户能够容易地编写和理解各种测试。测试夹具(Fixture)函数常被用来向测试函数添加某个参数,并返回不同的值。在Pytest中,您可以通过使用一个夹具来模块化另外一个。同时,用户可以使用多个夹具,在无需重写测试用例的情况下,将测试覆盖到所有参数的组合。Pytest开发人员通过发布各种实用插件,来保持框架的可扩展性。例如:pytest-xdist可以在不使用其他测试器的情况下,被用于执行并行测试。同时,单元测试也可以在无需复制任何代码的情况下,实现参数化。通过为开发人员提供各种特殊的例程,它能够使得测试用例的编写更为简单、更不易出错,同时代码也会变得更短、更易被理解。缺点上述提及的特殊例程,也意味着用户必须放弃一定的兼容性。虽然方便了用户编写测试用例,但是这些用例却无法与任何其他的测试框架一起被使用。Pytest的特点与竞品比较就编写功能性测试用例和开发复杂的框架而言,Pytest胜过下面将要提到的UnitTest。不过,它和Robot Framework类似,仅适用于开发出简单的测试框架。如果您正在考虑使用Pytest,请进一步参考《使用Pytest和Selenium WebDriver实现测试自动化》。3.UnitTest/PyUnit受到了JUnit启发的UnitTest/PyUnit,也是一种标准化的针对单元测试的Python类自动化测试框架。它的基类TestCase提供了各种断言方法、以及所有清理和设置的例程。因此,TestCase子类中的每一种方法都是以“test”作为名词前缀,以标识它们能够被作为测试用例所运行。用户可以使用load方法和TestSuite类来分组、并加载各种测试。当然,您也可以通过联合使用,来构建自定义的测试运行器。正如我们使用Junit去测试Selenium那样,UnitTest也会用到UnitTest-sml-reporting、并能生成各种XML类型的报告。使用先决条件由于UnitTest默认使用了Python,因此我们并不需要什么先决条件。除了需要具备Python框架的基本知识,您也可以额外地安装pip、以及用于开发的IDE工具。优点开发人员并不需要安装任何其他的模块。UnitTest是xUnit的衍生产品,其工作原理与其他xUnit框架十分类似。因此对于那些没有过硬Python背景的人来说,也能很快地上手。用户能够以更为简单的方式运行单个测试用例。您只需在终端上预定好名称,该框架便可灵活地执行各种用例的测试,并产生精炼的输出。它能够在几毫秒内生成各种测试报告。缺点虽然该框架常用snake_case来命名各种Python代码,但是由于它源自Junit,因此仍保留了一些传统的camelCase命名方法。这往往会让人产生混淆。由于它过多地支持了抽象方法,因此造成了测试代码的目的有时不够清晰。 需要大量的样板代码。PyUnit的特点与竞品比较和部分Python开发人员的观点相似,我认为:Pytest能够培养测试人员以非常紧凑的方式编写出更好的自动化代码,这一编程习惯。尽管UnitTest是Python默认的自动化测试框架,但是其工作原理、及命名规则仍与标准的Python代码略有不同。同时,它也需要太多的样板代码。因此该框架并不太受欢迎。4.Behave我们都知道:行为驱动开发(behavior-driven development,BDD),是一种基于敏捷软件开发的方法。它能够鼓励开发人员、业务参与者和QA人员,三者之间的协作。作为另一种Python测试框架,Behave允许团队避开各种复杂的情况,去执行BDD测试。从本质上说,该框架与SpecFlow和Cucumber非常相似,常被用于执行自动化测试。用户可以通过简单易读的语言来编写测试用例,并能够在其执行期间粘贴到代码之中。而且,那些被设定的行为规范与步骤,也可以被重用到其他的测试方案中。使用先决条件任何具备Python基础知识的人都可以使用Behave。其他先决条件还包括:您必须先安装Python 2.7.14及以上的版本。需要通过Python包管理器或pip来与Behave协作。大多数开发人员会选择Pycharm作为开发环境,当然您也可以选用其他的IDE工具。优点由于系统行为使用了半正式(semi-formal)语言、以及域词汇表(domain vocabulary),因此Behave有助于在组织中保持一致性的行为。让那些工作在不同模块上的开发团队,通过协调处理来具有类似的特征。其构建的各个功能块能够执行各种测试用例。由于具有更多值得用户推理和思考的细节,因此目标产品会具有更好的规范性。根据类似的规范格式,它能够让项目经理和利益相关者,对开发团队和QA团队的输出具有更清楚地了解。缺点只适用于黑盒测试。Behave的特点与竞品比较Behave最适合于诸如简单Web测试之类的黑盒测试。但是,对于那些具有复杂场景的集成测试与单元测试而言,Behave并不是一个很好的选择。作为Behave的替代品,一些开发与测试人员会推荐使用pytest-bdd。该工具融合了Pytest的所有优点,并实现了各种行为驱动测试的场景。如果您正在考虑使用Behave,那么您可以借用《Behave with Selenium》(请参见https://www.lambdatest.com/support/docs/display/TD/Behave+with+Selenium+-+Running+Behave+Automation+Scripts+on+LambdaTest+Selenium+Grid)中提到的自动化脚本。5.LettuceLettuce是另一种基于Cucumber和Python的行为驱动类自动化工具。Lettuce主要专注于那些具有行为驱动开发特征的普通任务。它不但简单易用,而且能够使得整个测试过程更流畅、甚至更有趣。使用先决条件您需要安装带有IDE的Python 2.7.14、及以上的版本。当然,您也可以使用Pycharm或任何其他IDE工具。同时,您还需要安装Python包管理器。优点和其他BDD测试框架类似,Lettuce能够让开发人员创建多个场景,并用简单的自然语言去描述不同的功能。根据类似的规范格式,开发与QA团队能够协调共事。对于黑盒测试而言,Lettuce非常适合于那些行为驱动的测试用例。缺点为了成功地实现行为驱动测试,开发团队、QA人员以及利益相关者之间需要持续进行沟通。倘若缺乏此类沟通,则会产生流程模糊不清,并让团队遇到问题。 竞品比较在普通开发人员和自动化测试人员看来,Cucumber在执行BDD测试方面更为实用。而在Python开发和QA人员看来,Pytest-bdd才是的。Pytest的强大之处在于:其框架实现了紧凑且易于理解的代码,并能紧密地结合到行为驱动的测试之中。结语综上所述,在上述五种自动化测试的Python框架中,Pytest、Robot Framework和UnitTest可主要用于功能与单元测试,而Lettuce和Behave仅适用于行为驱动测试。通过进一步比较,我们认为:对于功能测试而言,Pytest是的。如果您是基于Python自动化测试的新手,那么Robot Framework是的入门工具。虽然其功能有所受限,但是它非常容易上手。对于基于Python的BDD测试而言,Lettuce和Behave同样优秀。不过,如果你已经有了一定的Pytest经验,那么请使用Pytest-bdd,希望本文能够帮助您选出合适的Python测试框架,并顺利开展测试工作。
  • [问题求助] 使用excelKillProcess结束Excel进程时报错,远程过程调用失败
    在关闭excel时,使用结束excel进程空间时弹出报错,‘远程过程调用失败’,尝试使用关闭工作簿时会报错‘RPC服务器不可用’,请问如何解决此问题
  • [技术交流] 单元测试
     1         单元测试的重要性1.1      一些错误的认识在实际的单元测试过程中总会有一些错误的认识左右着我们,使之成为单元测试最大的障碍,在此将其一一分析如下:它太浪费时间了,现在要赶进度,时间上根本不允许,或者随便做做应付领导。我是一个很棒的程序员,我写的代码肯定是没有问题的。做单元测试太烦了,直接集成,到时有问题在集成测试时肯定能发现的,实在不行在系统测试总该能发现吧。它仅仅是证明这些代码做了什么。对于以上错误认识的产生归根结底还是由于对单元测试的理解还是不够,没有真正认识到单元测试的重要性。1.2      测试的重要性单元测试是软件测试的基础,因此单元测试的效果会直接影响到软件的后期测试,最终在很大程度上影响到产品的质量。从如下几个方面就可以看出单元测试的重要性在何处。时间方面:如果认真的做好了单元测试,在系统集成联调时非常顺利,因此会节约很多时间,反之那些由于因为时间原因不做单元测试或随便做做的则在集成时总会遇到那些本应该在单元测试就能发现的问题,而这种问题在集成时遇到往往很难让开发人员预料到,最后在苦苦寻觅中才发现这是个很低级的错误而在悔恨自己时已经浪费了很多时间,这种时间上的浪费一点都不值得,正所谓得不偿失。 测试效果:根据以往的测试经验来看,单元测试的效果是非常明显的,首先它是测试阶段的基础,做好了单元测试,在做后期的集成测试和系统测试时就很顺利。其次在单元测试过程中能发现一些很深层次的问题,同时还会发现一些很容易发现而在集成测试和系统测试很难发现的问题。再次单元测试关注的范围也特殊,它不仅仅是证明这些代码做了什么,最重要的是代码是如何做的,是否做了它该做的事情而没有做不该做的事情。测试成本:在单元测试时某些问题就很容易发现,如果在后期的测试中发现问题所花的成本将成倍数上升。比如在单元测试时发现1个问题需要1个小时,则在集成测试时发现该问题需要2个小时,在系统测试时发现则需要3个小时,同理还有定位问题和解决问题的费用也是成倍数上升的,这就是我们要尽可能早的排除尽可能多的bug来减少后期成本的因素之一。 产品质量:单元测试的好与坏直接影响到产品的质量,可能就是由于代码中的某一个小错误就导致了整个产品的质量降低一个指标,或者导致更严重的后果,如果我们做好了单元测试这种情况是可以完全避免的。    综上所述,单元测试是构筑产品质量的基石,我们不要因为节约单元测试的时间不做单元测试或随便做而让我们在后期浪费太多的不值得的时间,我们也不愿意因为由于节约那些时间导致开发出来的整个产品失败或重来!1.3      具有的优点1. 它是一种验证行为。程序中的每一项功能都是测试来验证它的正确性,为以后的开发提供支缓。就算是开发后期,我们也可以轻松的增加功能或更改程序结构,而不用担心这个过程中会破坏重要的东西。而且它为代码的重构提供了保障,这样,我们就可以更自由的对程序进行改进。2.它是一种设计行为。编写单元测试将使我们从调用者观察、思考,特别是先写测试(test-first),迫使我们把程序设计成易于调用和可测试的,即迫使我们解除软件中的耦合。另外还可以使编码人员在编码时产生预测试,将程序的缺陷降低到最小。3.它是一种编写文档的行为。单元测试是一种无价的文档,它是展示函数或类如何使用的最佳文档。这份文档是可编译、可运行的,并且它保持最新,永远与代码同步。4.它具有回归性。自动化的单元测试避免了代码出现回归,编写完成之后,可以随时随地的快速运行测试。 2         单元测试的基本理论2.1      基本概念1. 单元测试:单元测试又称模块测试,属于白盒测试,是最小单位的测试。模块分为程序模块和功能模块。功能模块指实现了一个完整功能的模块(单元),一个完整的程序单元具备输入、加工和输出三个环节。而且每个程序单元都应该有正规的规格说明,使之对其输入、加工和输出的关系做出名明确的描述。2.测试驱动:驱动被测试模块正常运行起来的实体3.测试桩:代替被测模块调用的子模块的实体,该实体一般为桩函数。4. 测试覆盖:评测测试过程中已经执行的代码的多少。5.覆盖率:代码的覆盖程度,一种度量方式。针对代码的测试覆盖率有许多种度量方式,定义如下: 语句覆盖(StatementCoverage):也称为行覆盖(linEC),段覆盖(segmentcoverage)和基本块覆盖(bAS)。它度量每一个可执行语句是否被执行到了。icblockcoverageoverage判定覆盖(DecisionCoverage):也被称为分支覆盖(branchcoverage),所有边界覆盖(all-edgescoverage),基本路径覆盖(basispathcoverage),判定路径覆盖(decision-decision-path或DDPtesting)。它度量是否每个BOO型的表达式取值true和false在控制结构中都被测试到了。L 条件覆盖(ConDI):它独立的度量每一个子表达式,报告每一个子表达式的结果的true或false。这个度量和判定覆盖(decisioncoverage)相似,但是对控制流更敏感。不过,完全的条件覆盖并不能保证完全的判定覆盖。tionCoverage 路径覆盖(PathCoverage):也称为断言覆盖(prEDI),它度量了是否函数的每一个可能的分支都被执行了。路径覆盖的一个好处是:需要彻底的测试。但有两个缺点:一是,路径是以分支的指数级别增加的,例如:一个函数包含10个IF语句,就有1024个路径要测试。如果加入一个IF语句,路径数就达到2048;二是,许多路径不可能与执行的数据无关。catecoverage循环覆盖(LOOP):这个度量报告你是否执行了每个循环体零次、只有一次还是多余一次(连续地)。对于do-while循环,循环覆盖报告你是否执行了每个循环体只有一次还是多余一次(连续地)。这个度量的有价值的方面是确定是否对于while循环和for循环执行了多于一次,这个信息在其它的覆盖率报告中是没有的。 2.2      测试的内容单元测试的对象是软件设计的最小单位——模块或函数,单元测试的依据是详细设描述。测试者要根据详细设计说明书和源程序清单,了解模块的I/O条件和模块的逻辑结构。主要采用白盒测试的测试用例,辅之以黑盒测试的测试用例,使之对任何合理和不合理的输入都能鉴别和响应。要求对所有的局部和全局的数据结构、外部接口和程序代码的关键部分进行桌面检查和代码审查。在单元测试中,需要对下面5个方面的内容进行测试,也是构造测试用例的基础。1)   模块接口:测试模块的数据流。如果数据不能正确地输入和输出,就谈不上进行其他测试。因此,对于模块接口需要如下的测试项目:调用所测模块时的输入参数与模块的形式参数在个数、属性、顺序上是否匹配;所测模块调用子模块时,它输入个子模块的参数与子模块的形式参数在个数、属性、顺序上是否匹配;是否修改了只做输入用的形式参数;输出给标准函数的参数在个数、属性、顺序上是否匹配;全局变量的定义在各模块中是否一致; 限制是否通过形式参数来传送。2)  局部数据结构测试:模块的局部数据结构是最常见的错误来源,应设计测试用例以检查以下各种错误: 检查不正确或不一致的数据类型说明;使用尚未赋值或尚未初始化的变量; 错误的初始值或错误的默认值;变量名拼写错误或书写错误; 不一致的数据类型。3)路径测试:对基本执行路径和循环进行测试会发现大量的错误。根据白盒测试和黑盒测试用例设计方法设计测试用例。设计测试用例查找由于错误的计算、不正确的比较或不正常的控制流而导致的错误。常见的不正确的计算有:Ø         运算的优先次序不正确或误解了运算的优先次序;Ø         运算的方式错误(运算的对象彼此在类型上不相容);Ø         算法错误;Ø         初始化不正确;Ø         运算精度不够;Ø         表达式的符号表示不正确等。 常见的比较和控制流错误有:Ø         不同数据类型的比较;Ø         不正确的逻辑运算符或优先次序;Ø         因浮点运算精度问题而造成的两值比较不等;Ø         关系表达式中不正确的变量和比较符;Ø         “差1错”,即不正确地多循环或少循环一次;Ø         错误的或不可能的循环终止条件;Ø         当遇到发散的迭代时不能终止循环;Ø         不适当地修改了循环变量等。4) 错误处理测试:比较完善的模块设计要求能预见出错的条件,并设置适当的出错处理对策,以便在程序出错时,能对出错程序重新做安排,保证其逻辑上的正确性。这种出错处理也是模块功能的一部分。表明出错处理模块有错误或缺陷的情况有:出错的描述难以理解;出错的描述不足以对错误定位和确定出错的原因;显示的错误与实际的错误不符;对错误条件的处理不正确;在对错误进行处理之前,错误条件已经引起系统的干预; 如果出错情况不予考虑,那么检查恢复正常后模块可否正常工作。5) 边界测试:边界上出现错误上常见的。设计测试用例检查: 在n次循环的第0次、1次、n次是否有错误;运算或判断中取最大最小值时是否有错误;数据流、控制流中刚好等于、大于、小于确定的比较值时是否出现错误。 2.3      测试的环境构成何时进行单元测试?单元测试在编码阶段进行。在源程序代码编制完成、经过评审和验证、确认没有语法错误之后,就可以开始进行单元测试的测试用例设计。要利用软件设计文档,设计可以验证程序功能、找出程序错误的多个测试用例。对于每一组输入,应该有预期的正确结果。在单元测试时,如果模块不是独立的程序,需要辅助测试模块,有两种辅助模块:驱动模块(Driver):所测模块的主程序。它接收测试数据,把这些数据传递给所测试模块,最后再输出测试结果。当被测试模块能完成一定功能时,也可以不要驱动模块。 桩模块(Stub):用来代替所测模块调用的子模块。      被测试模块、驱动模块和桩模块共同构成了一个测试环境,如下图所示:3         测试方法与过程3.1      用例设计1.测试用例的组成(在单元测试中测试用例基本上由测试脚本组成)用例运行前置条件被测模块/单元所需环境(全局变量赋值或初始化实体)启动测试驱动设置桩调用被测模块设置预期输出条件判断2.测试用例的设计原则一个好的测试用例在于能够发现至今没有发现的错误;测试用例应由测试输入数据和与之对应的预期输出结果这两部分组成;在测试用例设计时,应当包含合理的输入条件和不合理的输入条件;为系统运行起来而设计测试用例;为正向测试而设计测试用例;为逆向测试而设计测试用例;为满足特殊需求而设计测试用例;为代码覆盖而设计测试用例;3.用例设计方法1)        规范(规格)导出发2)        等价类划分法3)        边界值分析法4)        状态转移测试法5)        分支测试法6)        条件测试法7)        数据定义-使用测试法(又名数据流测试法)8)        内部边界值测试法9)        错误猜测法4. 特定的用例测试设计1)声明测试:检查模块中的所有变量是否被声明。经验表明,大量重要的错误都是由于变量没有被声明或没有被正确的声明而引起的。2)路径测试:要求模块中所有可能的路径都被执行一遍,属逻辑覆盖测试。基本路径测试:由于实际中,一个模块中的路径可能非常多,由于时间和资源有限,不可能一一测试到。这就需要把测试所有可能路径的目标减少到测试足够多的路径,以获得对模块的信心。要测试的最小路径集就是基本测试路径集。基本测试路径集要保证:每个确定语句的每一个方向要测试到;每条语句最少执行一次。3)循环测试:重点检查循环的条件-判断部分以及边界条件。测试循环是一种特殊的路径测试,因为循环比其他语句都复杂一些。循环中错误的发生机会比其他代码构成部分多。因此,对于任何给定的循环测试应该包括测试下面每一条件的测试用例: 循环不执行; 执行一次循环;执行两次循环;反映执行典型的循环的执行次数;如果有最大循环次数,最大循环次数减1;最大循环次数;大于最大循环次数。对于增量和减量不是1的FOR语句,要特别注意,因为程序员习惯于增量1。4) 循环嵌套:循环嵌套使逻辑的次数呈几何级数增长,设计测试嵌套循环的测试用例应该包括的测试条件有:把外循环设置为最小值,并运行内循环所有可能的情况;把内循环设置为最小值,并运行外循环所有可能的情况;把所有的循环变量都设置为最小值运行;把所有的循环变量都设置为最大值运行; 把外循环设置为最大值,并运行内循环所有可能的情况;把内循环设置为最大值,并运行外循环所有可能的情况;5) 边界值测试:指程序内部边界测试。检查确定代码在任何边界情况下都不会出差错。重点检查小于、等于和大于边界条件的情况。边界值测试是指专门设计用来测试当条件语句中引用的值处在边界或边界附近时系统反映的测试。被测试语句的最好的例子就是“IF-THEN…ELSE-ENDIF”部分。这样语句的例子如:IF a <= 123 THENb = 1ELSE IF a >= 123 THENb = 2ELSE b = 3END IF           上面例子中的边界值测试用例应该至少包括a的以下值:122,123,124。当a=123时,b=1还是2。(找出逻辑判断的矛盾)6)接口测试:检查模块的数据流(输入、输出)是否正确。检查输入的参数和声明的自变量的个数,数据类型和输入顺序是否一致。检查全局变量是否被正确的定义和使用等。7)确认测试:是否接受有效输入数据(操作),拒绝无效数据(操作)。8)事务测试:输入->输出,错误处理。3.2      用例执行一般来说,做单元测试均采用的是商用的测试工具或自行开发的测试工具,用例的编写都是在测试工具上完成,测试用例都是一些测试脚本,都以文件的方式来保存,故其用例的执行过程主要是由测试工具根据所编写的具体的测试用例脚本来完成,这样对于用例的管理和执行也非常灵活。在特定场合,比如某种压力测试或极限测试,对于测试执行过程时间很长时(几个小时以上),一般都预先编写好用例(确保用例无误),使用空闲机或非工作时间执行测试用例,这样操作起来较节约时间。在用例的执行过程中务必注意如下事项: 程序的执行过程―――便于构造发散用例不要放过任何细节―――这种细节可能就是问题 3.3      测试优化和策略在测试的过程中为了提高测试效率和效果,不断的减少冗余劳动,也为后期的回归测试和测试管理带来很大的方便,不至于感到测试很混乱无序。因此我们要对测试用例和测试执行进行不断的优化,以测试策略为指导方针进行测试。1、测试用例的优化    测试用例的优化主要是指用例的合并、修改和删除,减少冗余的无价值的测试,其优化依据来源于测试后的测试数据分析和评估,其中测试覆盖也是用例优化的主要参考。2、测试执行的优化        测试执行的优化主要是指测试步骤的优化,减少测试人员的手工操作,因为太多的手工操作会导致测试人员很厌倦,直接影响测试效果,优化依据来源于测试总结。3、测试策略    在测试过程中由于时间或资源的原因可能会使测试处于紧张的局面,在此情况下我们要采取一定的策略来解决此局面。策略来源于测试数据的分析,主要的方法是:为各模块制定测试优先级,其优先级的划分依据如下:哪些是重点模块? 哪些程序是最复杂、最容易出错的? 哪些程序是相对独立,应当提前测试的? 哪些程序最容易扩散错误?哪些程序是开发者最没有信心的? 80-20原则:80%的缺陷聚集在20%的模块中,经常出错的模块改错后还会经常出错,这种应该列入测试重点。 3.4      测试评估   单元测试完成以后,需要对单元测试的执行效果进行评估,主要从以下几方面进行:1)测试完备性评估,主要检查测试过程中是否已经执行了所有的测试用例,对新增的测试用例是否已及时更新测试方案等。2)代码覆盖率评估,主要是根据代码覆盖率工具提供的语句覆盖情况报告,检查是否达到方案中的要求,公司要求语句覆盖达到100%。但很多情况下,第一轮测试用例执行完后是很难达到的,这时在评估过程中要对覆盖率进行分析,主要从以下方面来考虑:不可能的路径或条件不可达的或冗余的代码不充分的测试用例3) 从覆盖的角度看,测试应该覆盖: 功能覆盖 输入域覆盖输出域覆盖函数交互覆盖代码执行覆盖   大多数有效的测试用例都来自于分析,而不是仅仅为了达到测试覆盖率目标而草率设计测试用例。千万不要误解测试覆盖,测试覆盖并不是我们最求的目的,它只是评价测试的一种方式,为测试提供指导和依据。3.5      测试过程1.测试过程中各种人员的作用系统分析设计人员     进行需求跟踪,确保系统需求的实现和更新。进行软件单元可测性分析,确定单元测试的对象、范围和方法。软件开发人员     负责编码和单元测试过程,完成单元测试计划、方案和报告。软件测试人员     参与单元测试计划、方案和报告的评审,对单元测试的计划、设计和执行质量进行监控。根据实际情况,可选择参与由开发人员负责的代码检视、单元测试等活动。 配置管理人员    对代码及单元测试文档进行配置管理。质量保证(QA)人员     参与编码与单元测试评审,对编码和单元测试过程进行审计。2.  单元测试输入《软件需求规格说明书》《软件详细设计说明书》《软件编码与单元测试工作任务书》《软件集成测试计划》《软件集成测试方案》用户文档3.单元测试的输出《单元测试计划》《单元测试方案》《需求跟踪说明书》或需求跟踪记录 代码静态检查记录《正规检视报告》 问题记录 问题跟踪和解决记录软件代码开发版本《单元测试报告》《软件编码与单元测试任务总结报告》3.6      测试实施1.  单元测试实施步骤1)        制定测试计划和测试方案(包括测试工具的选择)2)        根据计划和方案及相关输入文档编写测试用例3)        搭建测试环境4)        执行测试5)        记录和跟踪问题6)        编写测试报告和总结报告2.  单元测试实施遵循的原则 精心制定测试计划 严格评审测试计划 严格执行测试计划系统分析测试结果并提交报告4         常用测试工具介绍常用的C语言单元测试工具介绍如下: winAMS、CasePlayer21)        简介GAIO公司的覆盖率专家winAMS获得机能安全标百准ISO26262/IEC61508工具认证,是日本工业制造度领域普遍使用的针对C/C++的单元/集成测试工具。winAMS将通过交叉编译生成的原始代码作为评价代码,具有使用芯片仿真器进行仿真功能的测试工具。不仅可以对C/C++语言编写的程序进行逻辑水平的测试,还可以对嵌入式软件特有的依存于芯片的问题点进行确认。2)        功能特性尽可能使单元测试的环境与目标环境相同采用全面支持嵌入式微机的微机化功能测试平台环境不需要插入测试用代码直接使用目标机代码进行测试取得第三方认证机构TUVSUD对适用于汽车机能安全ISO26262软件工具的认证测试工程管理
  • [问题求助] 疑似web插件执行失败
    WeAutomate Studio已安装wa-web拓展模块谷歌浏览器也启用拓展程序但仍然无法捕捉网页元素,无法使用获取下载等控件求大神指点
  • [技术干货] 自动化测试——selenium(完结篇)-转载
     一、元素操作方法 方法: 1、.send_keys()  # 输入方法 2、.click()  # 点击方法 3、.clear()  # 清空方法 注意:在输入方法之前一定要清空操作!!  # 导包 from time import sleep from selenium import webdriver  # 实例化浏览器 driver = webdriver.Chrome()  # 打开网址 driver.get('https://www.baidu.com/')  # 需求 ele = driver.find_element_by_css_selector('#kw') ele.send_keys('易烊千玺') sleep(2)  # 清空 ele.clear() ele.send_keys('王嘉尔')  # 时间轴看效果 sleep(3)  # 关闭页面 driver.quit() 二、浏览器操作方法 常用的浏览器操作系统API  # 方法 """ 1、driver.maximize_window()  # 最大化浏览器 2、driver.set_window_size(w,h)  # 设置浏览器大小 单位像素 【了解】 3、driver.set_window_position(x,y)  # 设置浏览器位置  【了解】 4、driver.back() # 后退操作 5、driver.forward() # 前进操作 6、driver.refrensh() # 刷新操作 7、driver.close() # 关闭当前主窗口(主窗口:默认启动那个界面,就是主窗口) 8、driver.quit() # 关闭driver对象启动的全部页面 9、driver.title # 获取当前页面title信息 10、driver.current_url # 获取当前页面url信息 """ """ 应用:driver.maximize_windows()  # 窗口最大化      driver.set_window_size(w,h) # 设置浏览器大小 【了解】      driver.set_window_position(x,y) # 设置浏览器窗口位置 【了解】 """  from time import sleep from selenium import webdriver  driver = webdriver.Chrome()  driver.get('https://www.baidu.com/') # 窗口最大化 driver.maximize_window() sleep(1) # 设置浏览器宽,高 【了解】 driver.set_window_size(1000, 1000) sleep(1) # 设置窗口浏览器位置  【了解】 driver.set_window_position(200, 200)  sleep(3)  driver.quit()  """ driver.close() # 关闭当前主窗口,默认启动的界面就是主窗口 driver.quit() # 关闭全部页面 driver.title  # 获取页面标题 driver.current_url  # 获取页面地址  """  from time import sleep from selenium import webdriver  driver = webdriver.Chrome()  driver.get('https://www.sogou.com/') driver.find_element_by_link_text('图片').click()  # 这两个属性可以用来做断言使用 print("当前页面标题:", driver.title) print("当前页面的url:", driver.current_url)  # 这里关闭的是原始页面,而不是新的页面,只有完成页面切换才可以关闭新的页面 # 场景:关闭单个页面使用 driver.close() sleep(3)  # 关闭浏览器驱动对象的所有页面 driver.quit() 注意:driver.close() ,当前关闭的是主窗口,只有完成页面切换才可以关闭当前新的页面  提示:  1、driver.title 和 drivet.current_url是属性没有括号。应用场景:一般判断上不操作是否执行成功。  2、driver.maximize_window() 一般为前置代码放到获取driver地址后,进行浏览器窗口的最大化  3、driver.refresh() 向浏览器重新发出请求,刷新页面,在cookie 会用到  4、driver.close() 和 driver.quit() 的区别:  close():关闭当前主窗口 quit():关闭由driver对象启动的所有页面 如果只有一个窗口那么quit()和 close()没有区别。 三、获取元素信息操作 常用元素信息操作API  """ 方法: 1、text 获取元素的文本; 如:driver.text 2、size 获取元素的大小: 如:driver.size 3、get_attribute 获取元素属性值;如:driver.get_attribute("id") ,传递的参数是元素的属性名 4、is_displayed 判断元素是否可见 如:element.is_displayed() 5、is_enabled 判断元素是否可用 如:element.is_enabled() 6、is_selected 判断元素是否被选中 如:element.is_selected()  """ """ text  获取元素文本 ,没有() size  获取元素大小 ,没有() get_attribute("属性名") 获取的是属性值 """  from time import sleep from selenium import webdriver  driver = webdriver.Chrome()  driver.get('https://www.sogou.com/') ele = driver.find_element_by_id('query') print("目标元素尺寸:", ele.size)  new_ele = driver.find_element_by_id('hanyu') print("目标元素文本:", new_ele.text)  link = driver.find_element_by_link_text("图片") print("目标元素属性值:", link.get_attribute('id'))  sleep(3)  # 关闭浏览器驱动对象的所有页面 driver.quit()  """ is_displayed() 判断元素是否可见,如:element.is_displayed is_enabled() 判断元素是否可用, 如:element.is_enabled is_selected() 判断元素是否被选中,如:element.is_selected """  from time import sleep from selenium import webdriver  driver = webdriver.Chrome()  driver.get('file:///D:/桌面/page/注册A.html') # 判断元素是否可见,不可见并不代表不能定位 span = driver.find_element_by_name('sp1') print("元素是否可见:", span.is_displayed())  btn = driver.find_element_by_id('cancelA') print("元素是否可用:", btn.is_enabled())  check = driver.find_element_by_id('lia') print("元素是否被选中:", check.is_selected())  sleep(3)  # 关闭浏览器驱动对象的所有页面 driver.quit() 注意:里面的返回的结果都是True 和 False。  四、鼠标操作 (需要实例化鼠标对象) 1、我们有了鼠标为什么还要使用鼠标操作??  ​ 为了满足丰富的html鼠标效果,必须使用对应的方法。  2、鼠标时间对应的方法在那个类中?  ​ ActionChains类,实例化 鼠标对象  导包:  from selenium.webdriver.common.action_chains import ActionChains 1 3、鼠标事件常用的操作 ☆  """ 1、context_click(element) # 右击 2、double_click(element)  #双击 3、double_and_drop(source, target)  # 拖拽 4、move_to_element(element)  # 悬停 【重点】 5、perform()  # 执行以上事件的方法 【重点】 """ 4.1 鼠标右键及双击 """ 鼠标操作: context_click() 右键 double_click() 鼠标双击 """ from time import sleep from selenium import webdriver from selenium.webdriver import ActionChains  driver = webdriver.Chrome() driver.get('https://www.baidu.com/') # 定位目标 ele = driver.find_element_by_id('kw') # 实例化 鼠标对象 action = ActionChains(driver)、  # 鼠标右键 action.context_click(ele)  # 鼠标双击 action.double_click(ele)  # 鼠标执行操作!!!不执行没效果 action.perform()  sleep(3)  driver.quit() 4.2 鼠标拖拽 """ 鼠标操作: # 鼠标拖拽 action.drag_and_drop(source, target) """ from time import sleep from selenium import webdriver from selenium.webdriver import ActionChains  driver = webdriver.Chrome() driver.get('file:///D:/桌面/page/drag.html')  red = driver.find_element_by_xpath('//*[@id="div1"]') blue = driver.find_element_by_xpath('//*[@id="div2"]')  # 实例化鼠标 action = ActionChains(driver) # 鼠标拖拽 action.drag_and_drop(red, blue) # 鼠标执行 action.perform()  sleep(3)  driver.quit() 4.3 鼠标悬停 【重点】 """ 鼠标操作: # 鼠标悬停 【重点】 action.move_to_element(element) """ from time import sleep from selenium import webdriver from selenium.webdriver import ActionChains  driver = webdriver.Chrome() driver.get('https://www.baidu.com/') driver.maximize_window() ele = driver.find_element_by_id('s-usersetting-top')  # 实例化鼠标 action = ActionChains(driver) # 鼠标悬停 action.move_to_element(ele) # 鼠标执行 action.perform()  sleep(3)  driver.quit() 注意: selenium 框架虽然提供了 鼠标右键方法,但是没有提供选择右键菜单方法,可以通过键盘快捷键操作实现  五、键盘操作(不需要实例化对象)☆ 1、说明:键盘对应的方法在Keys类中  # 包 from selenium.webdriver.common.keys import Keys 2、快捷键(这里只讲windows操作系统的快捷键):  ​ CONTROL: Ctrl键  ​ BACK_SPACE : 等价于 BACKSPACE (删除)  ​ 其他:可以藏奥Keys底层的定义  3、应用  # 单键 element.send_keys(Keys.XXX) # 组合键 element.send_keys(Keys.XXX, 'a') # 注意这里的组合键都是小写 """ 键盘操作 """ from time import sleep from selenium import webdriver from selenium.webdriver.common.keys import Keys  driver = webdriver.Chrome() driver.get('https://www.baidu.com/')  ele = driver.find_element_by_id('kw') ele.send_keys('易烊千玺') sleep(1) ele.send_keys(Keys.BACK_SPACE) sleep(1) # 组合键 Ctrl + a 全选 ,注意这里的组合键都是小写 ele.send_keys(Keys.CONTROL, 'a') sleep(1) ele.send_keys(Keys.CONTROL, 'x') sleep(1) ele.send_keys(Keys.CONTROL, 'v')  sleep(3)  driver.quit()  六、元素等待 1、为什么要设置元素等待  ​ 由于电脑配置或网络原因,在查找元素时,元素代码未在第一时间内被加载出来,而抛出未找到元素异常。  2、什么是元素等待  ​ 元素在第一次未找到时,元素等待设置的时长被激活,如果在设置的有效时长内找到元素,继续执行代码,如果超出设置的时长未找打元素,抛出未找到元素异常。  3、元素等待分类  ​ 隐式等待:针对全局元素生效;(讲这个)  ​ 显示等待:稍微麻烦,有兴趣的可以下去了解,他是针对单个元素生效。  隐式等待方法:  driver.implicitly_wait(30) # 一般情况下设置30秒 1 ​ 特色:  1. 针对所有元素生效。 2. 一般情况下为前置必写代码(1.获取浏览器驱动对象;2. 最大化浏览器;3. 设置隐式等待) 1 2 """ 隐式等待 """ from time import sleep from selenium import webdriver from selenium.webdriver.common.keys import Keys  driver = webdriver.Chrome() # 1、获取浏览器驱动对象 driver.get('file:///D:/桌面/page/注册A等待.html') # 2、窗口最大化 driver.maximize_window() # 3、设置隐式等待 driver.implicitly_wait(30) ele = driver.find_element_by_id('userA') ele.send_keys('admin')  sleep(3)  driver.quit() 七、下拉框(需要实例化下拉框) 1、为什么单独使用下拉框?  ​ 1)、如果option选项没有value值的化,css定位或其他定位就不太方便。  2、使用Select类  ​ 1)、导包:from selenium.webdriver.support.select improt Select  ​ 2)、实例化下拉框:s = Select(element)  ​ 3)、调用方法:s.select_by_index()索引从0开始  3、Select类提供的方法  ​ 1)、select_by_index() # 通过索引定位  ​ 2)、select _by_value() # 通过value值  ​ 3)、select_by_visible_text() # 显示文本  """ Select类方法: 需要实例化下拉框元素定位 """ from time import sleep  from selenium import webdriver from selenium.webdriver.support.select import Select  driver = webdriver.Chrome() driver.get('file:///D:/桌面/page/注册A.html') ele = driver.find_element_by_id('selectA')  # 实例化下拉框 s = Select(ele)  # index 索引方法 s.select_by_index(1) sleep(1)  # value 属性值选择目标元素 s.select_by_value('sz') sleep(1)  # text 采用文本的方式选择目标信息 s.select_by_visible_text('A北京')  sleep(3)  driver.quit() 自定义弹窗,由于可以鼠标右击检查选项获取元素信息,所以出现自行已弹窗的时候,直接定义目标元素,并进行移除操作即可。  九、滚动条 1、为什么要是用滚动条?  ​ 在一些特殊场景中,一些按钮是在页面最下角,需要使用滚动条拉到最底层。  2、操作步骤  Selenium框架中没有专门处理滚动条的方法,需要通过调用 Js 代码实现操作;  ​ 1)、第一步:设置操作滚动条操作语句:js_down="window.scollTo(0,1000)"  ​ > 0:为左边距-----》水平滚动条  ​ > 1000: 为垂直滚动条  ​ 2)、第二步:调用执行js方法,将设置js语句传入方法中  ​ > 方法:driver.execute_script(js_down)  ​  """ 滚动条:selenium中没有滚动条方法,需要js代码实现 1、准备js代码:"window.scrollTo(0, 1000)" 2、执行js代码:driver.execute_script(js的变量) """ from time import sleep from selenium import webdriver  driver = webdriver.Chrome()  driver.get('file:///D:/桌面/page/注册A.html') sleep(2) # 1、准备js代码 js_down = "window.scrollTo(0, 1000)" # 2、执行js代码 driver.execute_script(js_down)  sleep(3)  driver.quit() 十、切换frame表单 ☆ 1、应用场景:  处于frame 中的元素,虽然可以获取元素信息,但是代码执行时无法定位元素,因此需要先切换到frame,再进行元素定位操作。  2、如何切换frame  方法:driver.switch_to.frame("id/name/element") 传入的是代表frame唯一的特征值  """ frame的切换 """ from time import sleep from selenium import webdriver  driver = webdriver.Chrome()  driver.get('file:///D:/桌面/page/注册实例.html')  # 切换到frame driver.switch_to.frame('idframe1') # 在frame表单中填写信息 driver.find_element_by_id('userA').send_keys('admin')  sleep(3)  driver.quit() 10.1 连续切换frame 说明:如果要连续切换frame必须要先回到默认页面,才能够实现下一个frame的切换  回到主页面的方法:driver.switch_to.default_content()  """ 需要默认切换到frame 方法:driver.switch_to.default_content() """ from time import sleep from selenium import webdriver  driver = webdriver.Chrome()  driver.get('file:///D:/桌面/page/注册实例.html')  driver.switch_to.frame('idframe1') driver.find_element_by_id('userA').send_keys('admin')  driver.switch_to.default_content() driver.switch_to.frame('myframe2') driver.find_element_by_id('userB').send_keys('admin4')  sleep(3)  driver.quit() 十一、多窗口的切换 ☆ 1、为什么要切换多窗口  ​ 页面是存在多窗口的,但是selenium默认焦点只会在主窗口上的所有元素,不切换窗口,就不能操作除主窗口以外的窗口内元素。  2、如何切换  每个窗口都有唯一的一个句柄值,那么我们就可以通过句柄值来完成窗口的切换操作  ​ 方法:  ​ 1)、driver.current_window_handle (获取当前的句柄值)  ​ 2)、driver.window_handles ( 获取当前由driver启动所有窗口句柄)  ​ 3)、driver.switch_to.window(handle) —> 切换窗口  """ 多窗口切换 driver.current_window_handle  获取当前的句柄值 driver.window_handles  获取driver启动的所有窗口句柄 driver.switch_to.window(handles[-1]) 切换窗口操作 """ from time import sleep  from selenium import webdriver  driver = webdriver.Chrome()  driver.get('file:///D:/桌面/page/注册实例.html')  driver.find_element_by_id('ZCB').click() # 1、获取当前的句柄值 # print("当前的句柄值是:", driver.current_window_handle)  # 2、 # 1).切换窗口操作,driver.window_handles 获取driver启动的所有窗口句柄 handles = driver.window_handles  # 2).切换窗口工作 driver.switch_to.window(handles[-1]) driver.find_element_by_id('userB').send_keys('admin9')  sleep(3)  driver.quit() 注意:这里的窗口切换也对应到了 close() 方法的作用,现在使用close()就是关闭当前页面,如果还想重新操作原始页面,务必完成窗口切换。  十二、截图操作 使用的方法:  driver.get_screenshot_as_file(imgepath)  参数:  imagepath:为图片要保存的目录地址及文件名称  """ 截图:driver.get_screenshot_as_file(imgepath) """ from time import sleep  from selenium import webdriver  driver = webdriver.Chrome()  driver.get('https://www.baidu.com/')  driver.find_element_by_xpath('//*[@id="kw"]').send_keys('易烊千玺') # 截图方法,建议使用png格式 , ./为当前路径,  ../为上一级路径 driver.get_screenshot_as_file('./info.png')  sleep(3)  driver.quit()  注意:指定图片存放的路径,需要自己手动创建文件夹  十三、验证码 1、什么是验证码?  ​ 一种随机生成的信息(文字,数字,图片)  2、验证码的作用?  ​ 防止恶意请求  3、验证码的处理  ​ 这边讲的是cookie解决  4、使用cookie 登录  ​ 客户端登录账号后,将登录状态的想关 cookie 信息发给服务器保存,再发送去请求,携带cookie信息如果跟服务器保留的一致,则服务器认为客户端是登录状态。  5、这里实现自动登录的功能  ​ 1)、准备工作,在客户端登录的状态下,获取cookie字段   2、方法步骤:  1、整理cookie信息为字典数据,对应的是name和value,保存的一个变量中 2、调用方法添加cookie     driver.add_cookie(cookie变量) # 3、刷新页面 -->发送cookie给服务器验证     driver.refresh() cookie 的value就不给你们了,怕你们登录我的账号😂😂😂  """ 验证码: {'name':'BDUSS', 'value':'............................'} """ from time import sleep  from selenium import webdriver  driver = webdriver.Chrome()  driver.get('https://www.baidu.com/') driver.maximize_window()  # 1、整理cookie信息为字典数据,对应的是name和value,保存的一个变量中 cookie_value = {'name':'BDUSS', 'value':'........................'}  # 2、调用方法添加cookie driver.add_cookie(cookie_value)  # 3、刷新页面 -->发送cookie给服务器验证 driver.refresh()  sleep(3)  driver.quit() 演示:  ​ 终于把Selenium 给完结了,完结撒花❀❀❀❀❀❀❀❀❀❀ ,这里面的方法都要掌握,然后可以找需求文档练习,铁汁们,觉得笔者写的不错的可以点个赞哟❤🧡💛💚💙💜🤎🖤🤍💟,收藏关注呗,你们支持就是我写博客最大的动力!!!! ———————————————— 版权声明:本文为CSDN博主「鸢也」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。 原文链接:https://blog.csdn.net/qq_54219272/article/details/123338773 
  • [技术干货] 应用场景分享——【appium】手机自动化环境搭建与案例分享
    手机自动化环境搭建与案例分享,如果附件中内容有需要修正的地方请跟帖,感谢支持!ext_appautomate_1_0_1.zip WeAutomate 设计器插件,需要导入。导入方式参考论坛帖子。样例及录像参考跟帖里的内容
  • [技术干货] python自动化测试——unittest二次开发之根据不同的粒度实现多线程执行测试用例(一)-转载
    一、Unittest用例的执行流程TestRunner的工作流程:遍历测试类中的测试用例,调用用例对象的run方法将测试用例的结果保存到TestResult中1、单线程执行测试用例特别注意:如果测试粒度按照文件为单位,那么文件中的测试类执行顺序就能得到保证如果测试粒度按照测试类为单位,那么测试类中的测试用例执行顺序就能得到保证如果测试粒度按照测试用例为单位,并且用例与用例之间有关联,那么测试用例执行顺序得不到保证import unittestfrom unittest import TestCase,TestSuite,TestLoader,TestResult'''粒度——》测试文件粒度——》测试类粒度——》用例级别'''from concurrent.futures.thread import ThreadPoolExecutor#todo 加载用例到测试套件中suite=unittest.defaultTestLoader.discover(r'D:\project_development\测试开发\day11\testcases')print('-------------------------单线程执行--------------------------------------')#todo 创建一个测试结果记录器result=unittest.TestResult()#todo 执行测试套件suite.run(result)print(suite)print('用例执行的结果,',result)二、测试套件的结构1、目录如下:2、测试文件test_demo1.pyimport timeimport unittestfrom ddt import ddt,data@ddtclass DemoA1(unittest.TestCase):@data(1,2,3,6)def test_demoa1(self,item):time.sleep(1)print('---------test_demoa1--------',item)@ddtclass DemoA2(unittest.TestCase):@data(1,2,3,6)def test_demoa2(self,item):time.sleep(1)print('---------test_demoa2--------',item)test_demo2.pyimport timeimport unittestfrom ddt import ddt,data@ddtclass DemoB1(unittest.TestCase):@data(1,2,3,6)def test_demob1(self,item):time.sleep(1)print('---------test_demob1--------',item)@ddtclass DemoB2(unittest.TestCase):@data(1,2,3,6)def test_demob2(self,item):time.sleep(1)print('---------test_demob1--------',item)test_demo3.pytest_demo4.py3、代码调试截图三、测试套件的结构1、将测试套件拆分为模块级别特别注意套件可以直接执行,套件中有run方法model_suite=[m for m in suite]result=unittest.TestResult()创建一个线程池对象,一共创建了4个模块,所以max_workers最大为4with ThreadPoolExecutor(max_workers=4) as tp: #创建一个线程池对象for i in model_suite:#i.run(result)tp.submit(i.run,result)2、将测试套件拆分为类级别class_suite=[]for m in suite:for c in m:class_suite.append(c)result=unittest.TestResult()with ThreadPoolExecutor(max_workers=8) as tp:for i in class_suite:tp.submit(i.run,result)3、将测试套件拆分为用例级别case_list=[]for m in suite:for c in m:for i in c:case_list.append(i)result=unittest.TestResult()with ThreadPoolExecutor(max_workers=32) as tp:for i in case_list:tp.submit(i.run,result)四、封装一个可以并发运行unittest测试用例的函数,参数接收两个参数,一个suite(测试套件)和mode(任务粒度:),根据传入的参数model,来对测试套件进行任务拆分,进行并发执行import unittestfrom unittest import TestCase,TestSuite,TestLoader,TestResult'''粒度——》用例级别粒度——》测试类'''from concurrent.futures.thread import ThreadPoolExecutor#todo 加载用例到测试套件中suite=unittest.defaultTestLoader.discover(r'D:\project_development\测试开发\day11\testcases')print('-------------------------多线程执行--------------------------------------')def run_cases(suite,model):#判断任务执行粒度task_list = []if model=='case':for m in suite:for c in m:for i in c:task_list.append(i)elif model=='cls':for m in suite:for c in m:task_list.append(c)else:task_list=[i for i in suite]result=unittest.TestResult()with ThreadPoolExecutor(max_workers=8) as tp:for i in task_list:tp.submit(i.run,result)run_cases(suite,'asd')————————————————版权声明:本文为CSDN博主「YZL40514131」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。原文链接:https://blog.csdn.net/YZL40514131/article/details/126982705
  • [问题求助] Roma API网关-测试接口:Authorization failed
    租户:Hi-stylhoc问题:综合安防-视频调阅板块功能调测:按调测步骤到最后一步Roma应用“Hi-stylhoc__视频标准接口”下,“获取设备列表”接口测试一直报:Authorization failed,最早相同的参数测试过一次,是正常的,今天测试一直不正常只传channel参数能正常查询,参数全传就报错,参数正确的:【日志信息】(可选,上传日志内容或者附件)
  • [新手课堂] 开始一个简单的接口测试(Python)
    利用python发送第一个请求关于HTTP请求,建议大家提前了解一下,再来看该篇文章该篇文章以简单的登录接口为例,干货来了:首先利用python发请求就会用到request库,先导入进来import requests1导入该库之后,就开始代码主体部分了#首先我们要把我们要测试接口API写进来url="http://localhost:8080/jwshoplogin/user/login.do"#紧接着把我们需要的参数定义一下userinfo={"username":"大娟",           "password":"Aa111111"}#参数定义完成后,就该让这个请求带着这个参数去乖乖的请求服务器了,下面的代码意思为将响应回来的信息以文本格式给到resres=requests.post(url,data=userinfo).text#得到响应信息后,将他打印出来print(res)这个为该接口正常响应回来的信息,作为测试我们当然要写个断言来判断他响应回来的对不对嘛,#.find这个方法是在响应回来的信息里面找登录成功四个字,找不到会返回-1负一的值msg=res.find("登录成功")if msg>0:    print("测试通过")else:    print("测试失败")一个简单的接口测试就这么完成了。将请求参数进行参数化处理这时候我们用到的是csv文件,现将csv库倒进来,还有我们必要的request库import requestimport csv下面是代码主体,具体解释我会写进代码里url='http://localhost:8080/jwshoplogin/user/login.do'#上面url就不解释了,但是userinfo我要说下,这里为空是因为我一会在文件里读取的内容放到这里面userinfo={}#下面的两个是对文件的操作,r为对文件读(read),w为对文件写(write)file1=open("interfacePara.csv",'r')file2=open("loginResult.csv","w")#这个意思为将读出来的内容放到table里面table=csv.reader(file1)for row in table:#第一次循环#将读到的第一行第一列的值给到username    userinfo["username"]=row[0]#将读到的第一行第二列的值给到password    userinfo["password"]=row[1]#这时候userinfo拿到的值为username="大娟",password="Aa111111"    response=requests.post(url,data=userinfo).text#查看一下响应回来的信息    print(response)    print(row[2]) #在响应回来的信息里面找csv文件里的第一行第三列的值,然后做判断,写到文件loginResult.csv里面    r=response.find(row[2])    if r>0:        print("测试通过") #因为在csv文件里每个分割是用逗号分割的所以这个要加上逗号,而且是英文格式的大家不要搞错,"\n"是换行的意思        file2.write(row[0]+","+row[1]+","+row[2]+","+"测试通过"+"\n")    else:        print("测试异常")        file2.write(row[0] + "," + row[1] + "," + row[2] + "," + "测试失败" + "\n")
  • [问题求助] 基础功能测试
    123456789
  • [问题求助] 代码提交任务完不成,接口测试任务也完不成了吗?
    你们可以吗?支支招撒
  • [专题汇总] 【XXX产品】【XXX功能】一句话描述问题
    软件测试的真正意义在于发现错误,而不在于验证软件是正确的。再严密的测试也不能完全发现软件当中所有的错误,但是测试还是能发现大部分的错误,能确保软件基本是可用的,所以在后续使用的过程中还需要加强快速响应的环节。结合软件测试的理论,故障暴露在最终客户端之前及时主动的去发现并解决。这一点就需要加强研发队伍的建设。在系统性能测试方面需要重视。经过这次培训中多个案例的讲解,让我了解到系统在上线之后会有很多不能预知的性能问题,需要在上线之前实现进行模拟,以规避风险,包括大数据量访问,高并发数等等。当然也有很多应对手段,没有哪种手段可称为最完美,只有最合适的,需要灵活掌握,综合运用以达到最优程度,这是个很值得研究的领域。
  • [交流吐槽] 日常任务代码提交和接口测试还是不行啊
    日常任务代码提交和接口测试还是不行啊,这周依然没恢复,大家都 能完成吗