《手把手教你》系列技巧篇(二十五)-java+ selenium自动化测试-FluentWait(详细教程)

简介: 【4月更文挑战第17天】其实今天介绍也讲解的也是一种等待的方法,有些童鞋或者小伙伴们会问宏哥,这也是一种等待方法,为什么不在上一篇文章中竹筒倒豆子一股脑的全部说完,反而又在这里单独写了一篇。那是因为这个比较重要,所以宏哥专门为她量身定制了一篇。FluentWait是Selenium中功能强大的一种等待方式,翻译成中文是流畅等待的意思。在介绍FluentWait之前,我们来讨论下为什么需要设置等待,我们前面介绍了隐式等待和显式等待。

1.简介

其实今天介绍也讲解的也是一种等待的方法,有些童鞋或者小伙伴们会问宏哥,这也是一种等待方法,为什么不在上一篇文章中竹筒倒豆子一股脑的全部说完,反而又在这里单独写了一篇。那是因为这个比较重要,所以宏哥专门为她量身定制了一篇。

FluentWait是Selenium中功能强大的一种等待方式,翻译成中文是流畅等待的意思。在介绍FluentWait之前,我们来讨论下为什么需要设置等待,我们前面介绍了隐式等待和显式等待。在现在很多软件产品为了加强前端的效果,采取了大量的AJAX 和Jquery技术,很多窗体内的数据,需要等待一会,才能加载完数据,才能出现一些元素,driver才能操作这些元素做一些事情。还有就是我们做一些操作,本身可能也需要等待一会才有数据显示。所以在自动化脚本开发过程,合理的设置时间等待是非常必要的,可以说百分之90以上的自动化测试用例执行失败,基本上是很时间等待有关系,造成元素没有及时在界面上显示,而报no such element子类的错误。

2.FluentWait的定义

简单来说,FluentWait就是一个普通的类,我们使用这个类能支持一直等待直到特定的条件出现。

1)是一个类而且是包org.openqa.selenium.support.ui的一部分

2)是Wait接口的一种实现

3)每个Fluent wait,我们可以设置等待最大时间,而且可以做设置等待的频率去检查一些特定的条件。

FluentWait 和 Explicit Wait的区别:简单来说就是Explicit Wait里有一些设定好了的前置条件的等待方式,而Fluent wait你可以设置自己的方法去处理各种等待的问题。

3.核心代码

3.1源码

宏哥先看一下FluentWait的源码,如何查看宏哥这里就不做赘述了。源码如下:

// Licensed to the Software Freedom Conservancy (SFC) under one

// or more contributor license agreements.  See the NOTICE file

// distributed with this work for additional information

// regarding copyright ownership.  The SFC licenses this file

// to you under the Apache License, Version 2.0 (the

// "License"); you may not use this file except in compliance

// with the License.  You may obtain a copy of the License at

//

//   http://www.apache.org/licenses/LICENSE-2.0

//

// Unless required by applicable law or agreed to in writing,

// software distributed under the License is distributed on an

// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY

// KIND, either express or implied.  See the License for the

// specific language governing permissions and limitations

// under the License.


package org.openqa.selenium.support.ui;


import com.google.common.base.Throwables;

import com.google.common.collect.ImmutableList;


import org.openqa.selenium.TimeoutException;

import org.openqa.selenium.WebDriverException;

import org.openqa.selenium.internal.Require;


import java.time.Clock;

import java.time.Duration;

import java.time.Instant;

import java.util.ArrayList;

import java.util.Collection;

import java.util.List;

import java.util.function.Function;

import java.util.function.Supplier;


/**

* An implementation of the {@link Wait} interface that may have its timeout and polling interval

* configured on the fly.

*

*

* Each FluentWait instance defines the maximum amount of time to wait for a condition, as well as

* the frequency with which to check the condition. Furthermore, the user may configure the wait to

* ignore specific types of exceptions whilst waiting, such as

* {@link org.openqa.selenium.NoSuchElementException NoSuchElementExceptions} when searching for an

* element on the page.

*

*

* Sample usage:

 
    

*   // Waiting 30 seconds for an element to be present on the page, checking

*   // for its presence once every 5 seconds.

*   Wait<WebDriver> wait = new FluentWait<WebDriver>(driver)

*       .withTimeout(30, SECONDS)

*       .pollingEvery(5, SECONDS)

*       .ignoring(NoSuchElementException.class);

*

*   WebElement foo = wait.until(new Function<WebDriver, WebElement>() {

*     public WebElement apply(WebDriver driver) {

*       return driver.findElement(By.id("foo"));

*     }

*   });

*

*

*

* This class makes no thread safety guarantees.

*

* @param  The input type for each condition used with this instance.

*/

public class FluentWait implements Wait {


 protected static final long DEFAULT_SLEEP_TIMEOUT = 500;


 private static final Duration DEFAULT_WAIT_DURATION = Duration.ofMillis(DEFAULT_SLEEP_TIMEOUT);


 private final T input;

 private final java.time.Clock clock;

 private final Sleeper sleeper;


 private Duration timeout = DEFAULT_WAIT_DURATION;

 private Duration interval = DEFAULT_WAIT_DURATION;

 private Supplier messageSupplier = () -> null;


 private List> ignoredExceptions = new ArrayList<>();


 /**

  * @param input The input value to pass to the evaluated conditions.

  */

 public FluentWait(T input) {

   this(input, Clock.systemDefaultZone(), Sleeper.SYSTEM_SLEEPER);

 }


 /**

  * @param input   The input value to pass to the evaluated conditions.

  * @param clock   The clock to use when measuring the timeout.

  * @param sleeper Used to put the thread to sleep between evaluation loops.

  */

 public FluentWait(T input, java.time.Clock clock, Sleeper sleeper) {

   this.input = Require.nonNull("Input", input);

   this.clock = Require.nonNull("Clock", clock);

   this.sleeper = Require.nonNull("Sleeper", sleeper);

 }


 /**

  * Sets how long to wait for the evaluated condition to be true. The default timeout is

  * {@link #DEFAULT_WAIT_DURATION}.

  *

  * @param timeout The timeout duration.

  * @return A self reference.

  */

 public FluentWait withTimeout(Duration timeout) {

   this.timeout = timeout;

   return this;

 }


 /**

  * Sets the message to be displayed when time expires.

  *

  * @param message to be appended to default.

  * @return A self reference.

  */

 public FluentWait withMessage(final String message) {

   this.messageSupplier = () -> message;

   return this;

 }


 /**

  * Sets the message to be evaluated and displayed when time expires.

  *

  * @param messageSupplier to be evaluated on failure and appended to default.

  * @return A self reference.

  */

 public FluentWait withMessage(Supplier messageSupplier) {

   this.messageSupplier = messageSupplier;

   return this;

 }


 /**

  * Sets how often the condition should be evaluated.

  *

  *

  * In reality, the interval may be greater as the cost of actually evaluating a condition function

  * is not factored in. The default polling interval is {@link #DEFAULT_WAIT_DURATION}.

  *

  * @param interval The timeout duration.

  * @return A self reference.

  */

 public FluentWait pollingEvery(Duration interval) {

   this.interval = interval;

   return this;

 }


 /**

  * Configures this instance to ignore specific types of exceptions while waiting for a condition.

  * Any exceptions not whitelisted will be allowed to propagate, terminating the wait.

  *

  * @param types The types of exceptions to ignore.

  * @param    an Exception that extends Throwable

  * @return A self reference.

  */

 public  FluentWait ignoreAll(Collection> types) {

   ignoredExceptions.addAll(types);

   return this;

 }


 /**

  * @param exceptionType exception to ignore

  * @return a self reference

  * @see #ignoreAll(Collection)

  */

 public FluentWait ignoring(Class exceptionType) {

   return this.ignoreAll(ImmutableList.>of(exceptionType));

 }


 /**

  * @param firstType  exception to ignore

  * @param secondType another exception to ignore

  * @return a self reference

  * @see #ignoreAll(Collection)

  */

 public FluentWait ignoring(Class firstType,

                               Class secondType) {


   return this.ignoreAll(ImmutableList.of(firstType, secondType));

 }


 /**

  * Repeatedly applies this instance's input value to the given function until one of the following

  * occurs:

  *

      *

  1. the function returns neither null nor false
  2.   *

  3. the function throws an unignored exception
  4.   *

  5. the timeout expires
  6.   *

  7. the current thread is interrupted
  8.   *

      *

      * @param isTrue the parameter to pass to the {@link ExpectedCondition}

      * @param     The function's expected return type.

      * @return The function's return value if the function returned something different

      * from null or false before the timeout expired.

      * @throws TimeoutException If the timeout expires.

      */

     @Override

     public  V until(Function isTrue) {

       Instant end = clock.instant().plus(timeout);


       Throwable lastException;

       while (true) {

         try {

           V value = isTrue.apply(input);

           if (value != null && (Boolean.class != value.getClass() || Boolean.TRUE.equals(value))) {

             return value;

           }


           // Clear the last exception; if another retry or timeout exception would

           // be caused by a false or null value, the last exception is not the

           // cause of the timeout.

           lastException = null;

         } catch (Throwable e) {

           lastException = propagateIfNotIgnored(e);

         }


         // Check the timeout after evaluating the function to ensure conditions

         // with a zero timeout can succeed.

         if (end.isBefore(clock.instant())) {

           String message = messageSupplier != null ?

                            messageSupplier.get() : null;


           String timeoutMessage = String.format(

               "Expected condition failed: %s (tried for %d second(s) with %d milliseconds interval)",

               message == null ? "waiting for " + isTrue : message,

               timeout.getSeconds(), interval.toMillis());

           throw timeoutException(timeoutMessage, lastException);

         }


         try {

           sleeper.sleep(interval);

         } catch (InterruptedException e) {

           Thread.currentThread().interrupt();

           throw new WebDriverException(e);

         }

       }

     }


     private Throwable propagateIfNotIgnored(Throwable e) {

       for (Class ignoredException : ignoredExceptions) {

         if (ignoredException.isInstance(e)) {

           return e;

         }

       }

       Throwables.throwIfUnchecked(e);

       throw new RuntimeException(e);

     }


     /**

      * Throws a timeout exception. This method may be overridden to throw an exception that is

      * idiomatic for a particular test infrastructure, such as an AssertionError in JUnit4.

      *

      * @param message       The timeout message.

      * @param lastException The last exception to be thrown and subsequently suppressed while waiting

      *                      on a function.

      * @return Nothing will ever be returned; this return type is only specified as a convenience.

      */

     protected RuntimeException timeoutException(String message, Throwable lastException) {

       throw new TimeoutException(message, lastException);

     }

    }

    3.2语法

    宏哥从源码中的Sample usage提取FluentWait的使用语法如下:

    Wait wait = new FluentWait(WebDriver reference)

    .withTimeout(timeout, SECONDS)

    .pollingEvery(timeout, SECONDS)

    .ignoring(Exception.class);


    WebElement foo=wait.until(new Function() {

    public WebElement applyy(WebDriver driver) {

    return driver.findElement(By.id("foo"));

    }

    });

    3.3例子

    有了语法,按照语法写一个简单例子,如下:

    Wait wait = new FluentWait(driver)

    .withTimeout(45, TimeUnit.SECONDS)

    .pollingevery(5, TimeUnit.SECONDS)

    .ignoring(NoSuchElementException.class);

    FluentWait主要使用两个参数–超时值(withTimeout)和轮询频率(pollingevery)。在上面的语法中,我们将超时值设置为45秒,轮询频率设置为5秒。等待条件的最长时间(45秒)和检查指定条件成功或失败的频率(5秒)。如果元素在此时间范围内可以查找到,它将执行下一步操作,否则它将抛出“ElementNotVisibleException”。

    3.4完整代码

    简单例子的完整代码如下:

    package lessons;

     

    import java.util.concurrent.TimeUnit;

     

    import org.openqa.selenium.By;

    import org.openqa.selenium.NoSuchElementException;

    import org.openqa.selenium.WebDriver;

    import org.openqa.selenium.WebElement;

    import org.openqa.selenium.chrome.ChromeDriver;

    import org.openqa.selenium.support.ui.FluentWait;

    import org.openqa.selenium.support.ui.Wait;

     

    import com.google.common.base.Function;

     

    public class FluentWait {

       public static void main(String[] args) throws Exception {

           

           System.setProperty("webdriver.chrome.driver", ".\\Tools\\chromedriver.exe");

           

           WebDriver driver = new ChromeDriver();

           

           driver.get("www.test.com");

           driver.manage().window().maximize();

           

           Wait wait = new FluentWait(driver)

                   

                      .withTimeout(45, TimeUnit.SECONDS)

               

                      .pollingEvery(5, TimeUnit.SECONDS)

               

                      .ignoring(NoSuchElementException.class);

               

           WebElement ele1 = wait.until(new Function() {

               

                public WebElement apply(WebDriver driver) {

           

                  return driver.findElement(By.id("xxxxxxx"));

           

                }

           

              });    

           

     

       }

     

    }

    4.项目实战

    由于没有现成的网页或者网站以供宏哥进行演示,因此宏哥自己简单写了一个demo以便演示使用。

    4.1测试网页代码

    宏哥这个网页主要思想就是点击按钮后10s倒计时,倒计时结束出现元素(一段英文文字)。

    测试网页test.html,参考代码如下所示:

    <html>

    <head>

    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />

    <title>北京-宏哥title>

    head>

    <style>

    #click {

       background-color: #4CAF50;

       border: none;

       color: white;

       padding: 15px 32px;

       text-align: center;

       text-decoration: none;

       display: inline-block;

       font-size: 16px;

       margin: 4px 2px;

       cursor: pointer;

    }

    .button {

       background-color: #f44336; 

       border: none;

       color: white;

       padding: 15px 32px;

       text-align: center;

       text-decoration: none;

       display: inline-block;

       font-size: 28px;

       margin-bottom: 100px;

    }

    #myAnchor

    {

     text-decoration:none;

     color: white;

    }

    style>

    <body>

       <div style=" text-align:center;">

           <div style="height: 100px;margin-top: 200px;">

           <button class="button"><a id="myAnchor" href="https://www.cnblogs.com/du-hong/">北京-宏哥a>button>br>

           <input type="button" value="Click Me - Fluent Wait" id="click" onclick="foo(this, 10000);"/>

           <p style='color:red; font-family: verdana; font-size: 20;align="center";' id="demo">Click and Wait for <b>10 secondsb> to view a message - "Software Testing Material - DEMO PAGE"p>

           div>

       div>    

    body>

    <script>

    function foo(obj, time) {

       obj.disabled = true;


       setTimeout(function() {

           var x = setInterval(function(){

                   time= time - 1000; //reduce each second

                   obj.value = (time/1000)%60;

                   if(time==0){

                           clearInterval(x);

                           obj.value = document.getElementById("demo").innerHTML = "Software Testing Material - DEMO PAGE";

                           obj.disabled = false;

                   }

           }, 1000);

       }, time-10000);

    }    


    script>

    html>

    下边宏哥编写java测试脚本。

    4.2代码设计

    设计思路:打开网页后,点击按钮开始5s频率的轮训查找元素,第一次没有找到,第二次10s刚好出现,代码也轮训查找也刚结束,没有找到,等到第三次英文文字出现了,代码也查找到,结束轮训,继续下一步操作。代码设计如下图所示:

    4.3Java参考代码

    宏哥首页用单元测试Junit测试一下写的方法有没有问题,没有问题,然后再调用。

    4.3.1运行代码

    1.运行代码,右键Run AS->JUnit Test,控制台输出,绿色的进度条证明写的方法没有问题,而且控制台也循环了2次(每次5s,一共10s),等待到了元素的出现并将其打印出来。如下图所示:

    2.运行代码后电脑端的浏览器的动作,如下小视频所示:

    4.4Java优化参考代码

    通过上边的单元测试我们知道写的方法没有问题,那么下边我们直接调用该方法即可。优化后代码如下:

    package lessons;

    import org.junit.Test;


    import java.util.NoSuchElementException;

    import java.util.concurrent.TimeUnit;


    import org.openqa.selenium.By;

    import org.openqa.selenium.WebDriver;

    import org.openqa.selenium.WebElement;

    import org.openqa.selenium.chrome.ChromeDriver;

    import org.openqa.selenium.support.ui.FluentWait;


    import com.google.common.base.Function;


    /**

    * @author 北京-宏哥

    *

    *《手把手教你》系列技巧篇(二十五)-java+ selenium自动化测试-FluentWait(详细教程)

    *

    * 2021年8月31日

    */

    public class FluentWaitClass {

       

       @Test

       public static void fluentWaitMethod(){

           System.setProperty("webdriver.gecko.driver", ".\\Tools\\chromedriver.exe"); //指定驱动路径

           WebDriver driver = new ChromeDriver();

           //最大化窗口  

           long startTime = System.currentTimeMillis(); //获取开始时间

           driver.manage().window().maximize();  

           long endTime = System.currentTimeMillis(); //获取结束时间

           System.out.println("程序运行时间1:" + (endTime - startTime) + "ms"); //输出程序运行时间

           driver.get("file:///C:/Users/DELL/Desktop/test/test.html");

           driver.findElement(By.xpath("//*[@id='click']")).click();

           

           

           FluentWait wait = new FluentWait(driver)

              .withTimeout(45, TimeUnit.SECONDS)

              .pollingEvery(5, TimeUnit.SECONDS)

              .ignoring(NoSuchElementException.class);

           long startTime1 = System.currentTimeMillis(); //获取开始时间

           WebElement element = wait.until(new Function() {

               public WebElement apply(WebDriver driver) {

                   WebElement element = driver.findElement(By.xpath("//*[@id='demo']"));

                   String getTextOnPage = element.getText();

                   if(getTextOnPage.equals("Software Testing Material - DEMO PAGE")){

                       System.out.println(getTextOnPage);

                       return element;

                   }else{

                       System.out.println("FluentWait Failed");

                       return null;

                   }

               }

           });

           long endTime1 = System.currentTimeMillis(); //获取结束时间

           System.out.println("程序运行时间3:" + (endTime1 - startTime1) + "ms"); //输出程序运行时间

           //driver.close();

       }

       

       public  static  void  main(String [] args){

           long startTime = System.currentTimeMillis(); //获取开始时间

           fluentWaitMethod();

           long endTime = System.currentTimeMillis(); //获取结束时间

           System.out.println("程序运行时间2:" + (endTime - startTime) + "ms"); //输出程序运行时间

       }

    }

    4.4.1运行代码

    1.运行代码,右键Run AS->java Application,控制台输出,如下图所示:

    2.运行代码后电脑端的浏览器的动作,如下小视频所示:

    5.小结

    1.在设计代码过程中会报错:Type mismatch: cannot convert from Test to Annotation   如下图所示:

    查了好多都说是:类名不能和注解名称相同的原因。后来宏哥检查了一下,不相同啊,但是宏哥为啥这里还会报这个错了。原来是宏哥没有导入单元测试的包,但是也没有提示导入包,因此宏哥将包导入,代码错误消失。如下图所示:

      好了,今天就分享到这里了,感谢你耐心的阅读!




    每天学习一点,今后必成大神-

    往期推荐(由于跳转参数丢失了,所有建议选中要访问的右键,在新标签页中打开链接即可访问):

    Appium自动化系列,耗时80天打造的从搭建环境到实际应用精品教程测试

    Python接口自动化测试教程,熬夜87天整理出这一份上万字的超全学习指南

    Python+Selenium自动化系列,通宵700天从无到有搭建一个自动化测试框架

    Java+Selenium自动化系列,仿照Python趁热打铁呕心沥血317天搭建价值好几K的自动化测试框架

    Jmeter工具从基础->进阶->高级,费时2年多整理出这一份全网超详细的入门到精通教程

    Fiddler工具从基础->进阶->高级,费时100多天吐血整理出这一份全网超详细的入门到精通教程

    Pycharm工具基础使用教程


    相关文章
    |
    1天前
    |
    敏捷开发 监控 测试技术
    探索自动化测试工具Selenium Grid的高效集成策略
    【4月更文挑战第30天】在现代Web应用的快速迭代和持续部署中,测试自动化已成为确保产品质量的关键。Selenium Grid作为一款支持多种浏览器和操作系统的测试工具,提供了并行执行测试用例的能力,极大地提升了测试效率。本文将深入探讨如何高效地将Selenium Grid集成到现有的测试框架中,以及实施过程中的最佳实践,帮助团队最大化测试覆盖率,同时降低资源消耗。
    |
    1天前
    |
    数据管理 测试技术
    深入理解自动化测试框架:以Selenium为例
    【4月更文挑战第30天】 随着软件开发的快速发展,自动化测试已经成为保证软件质量和提升开发效率的重要手段。本文将深入探讨自动化测试框架的核心概念,并以广泛应用的开源工具Selenium为例,解析其架构、原理及在实际项目中的运用。通过实例分析与性能评估,旨在为读者提供一套系统的自动化测试解决方案,并探讨其在复杂应用场景下的优化策略。
    |
    1天前
    |
    敏捷开发 前端开发 JavaScript
    深入理解自动化测试框架:以Selenium为例
    【4月更文挑战第30天】 在现代软件开发过程中,自动化测试已成为确保产品质量和加快市场投放的关键步骤。本文聚焦于流行的自动化测试框架——Selenium,探讨其架构、核心组件以及如何有效地利用Selenium进行Web应用测试。通过分析真实案例,我们将揭示Selenium在实际项目中的应用优势与面临的挑战,并提出优化策略。文章的目的在于帮助测试工程师深入理解Selenium,提升其在复杂项目中的运用效率。
    |
    1天前
    |
    前端开发 IDE 数据可视化
    深入理解与应用自动化测试框架Selenium的最佳实践
    【4月更文挑战第30天】 本文将深入剖析自动化测试框架Selenium的核心原理,并结合最佳实践案例,探讨如何有效提升测试覆盖率和效率。文中不仅涉及Selenium的架构解析,还将提供针对性的策略来优化测试脚本,确保测试流程的稳定性与可靠性。通过实例演示,读者可以掌握如何在不同测试场景中灵活运用Selenium,以及如何处理常见的技术挑战。
    |
    1天前
    |
    中间件 测试技术 API
    探索自动化测试工具的新边界:Selenium与Appium的集成实践
    【4月更文挑战第30天】 随着移动应用和Web应用的不断融合,传统的自动化测试工具需要适应新的测试环境。本文将详细分析Selenium和Appium这两款流行的自动化测试工具的集成实践,探讨如何构建一个能够同时支持Web和移动端应用的自动化测试框架。通过对比两者的技术架构、功能特性以及在实际项目中的集成过程,我们旨在为读者提供一个清晰的指导,帮助他们在复杂的应用环境中实现高效、稳定的自动化测试流程。
    |
    1天前
    |
    敏捷开发 监控 前端开发
    深入理解与应用自动化测试框架:以Selenium为例
    【4月更文挑战第30天】 在软件开发的快速迭代周期中,质量保证(QA)团队面临持续的压力,需确保产品在每次发布时都达到预期的质量标准。为了应对这一挑战,自动化测试成为了关键工具,它不仅提高了测试效率,还确保了测试的一致性和可重复性。本文将探讨自动化测试框架Selenium的核心组件、工作原理及其在实际测试中的应用。通过分析Selenium的优势和面临的常见问题,我们将讨论如何有效地集成Selenium到现有的测试流程中,以及如何克服常见的技术障碍。我们的目标是为读者提供一个清晰的指南,帮助他们理解和利用自动化测试框架来优化他们的软件测试实践。
    |
    1天前
    |
    Java 测试技术 Python
    《手把手教你》系列技巧篇(三十六)-java+ selenium自动化测试-单选和多选按钮操作-番外篇(详解教程)
    【4月更文挑战第28天】本文简要介绍了自动化测试的实战应用,通过一个在线问卷调查(&lt;https://www.sojump.com/m/2792226.aspx/&gt;)为例,展示了如何遍历并点击问卷中的选项。测试思路包括找到单选和多选按钮的共性以定位元素,然后使用for循环进行点击操作。代码设计方面,提供了Java+Selenium的示例代码,通过WebDriver实现自动答题。运行代码后,可以看到控制台输出和浏览器的相应动作。文章最后做了简单的小结,强调了本次实践是对之前单选多选操作的巩固。
    9 0
    |
    2天前
    |
    前端开发 JavaScript 测试技术
    深入探索自动化测试框架:Selenium与Appium的对比分析
    【4月更文挑战第29天】 在快速迭代的软件发展环境中,自动化测试已成为确保软件质量和加速产品上市的关键步骤。本文将重点探讨两种广泛使用的自动化测试框架——Selenium和Appium,通过对比它们的核心特性、适用场景及执行效率,为软件开发和测试团队提供选择指南。文章不仅分析了各自的技术架构和脚本语言支持,还讨论了它们在处理Web应用和移动应用测试时的优缺点,旨在帮助读者根据项目需求做出更加明智的选择。
    |
    2天前
    |
    IDE 测试技术 持续交付
    探索自动化测试工具Selenium的高效应用
    【4月更文挑战第29天】 在快速迭代的软件开发过程中,高效的测试策略是确保产品质量的关键。本文将深入探讨如何利用自动化测试工具Selenium来提高软件测试的效率和准确性。通过介绍Selenium的核心功能、脚本编写技巧以及与持续集成环境的集成方法,我们旨在为读者提供一个全面的Selenium应用指南。此外,我们还将讨论常见的问题解决策略,并通过案例分析展示如何有效地运用Selenium进行复杂的Web应用测试。
    |
    2天前
    |
    敏捷开发 机器学习/深度学习 Java
    Java中的异常处理机制深入理解与实践:持续集成在软件测试中的应用探索自动化测试在敏捷开发中的关键作用
    【4月更文挑战第29天】在Java编程中,异常处理是一个重要的概念。它允许开发者在程序执行过程中遇到错误或异常情况时,能够捕获并处理这些异常,从而保证程序的稳定运行。本文将详细介绍Java中的异常处理机制,包括异常的分类、异常的处理方式以及自定义异常等内容。 【4月更文挑战第29天】 随着敏捷开发和DevOps文化的兴起,持续集成(CI)已成为现代软件开发周期中不可或缺的一环。本文将探讨持续集成在软件测试领域内的关键作用、实施策略以及面临的挑战。通过对自动化构建、测试用例管理、及时反馈等核心要素的详细分析,揭示持续集成如何提高软件质量和加速交付过程。 【4月更文挑战第29天】 在当今快速发