《手把手教你》系列技巧篇(三十八)-java+ selenium自动化测试-日历时间控件-下篇(详解教程)

简介: 【5月更文挑战第2天】在自动化测试过程中,经常会遇到处理日期控件的点击问题。宏哥之前分享过一种方法,但如果输入框是`readonly`属性,这种方法就无法奏效了。不过,通过修改元素属性,依然可以实现自动化填写日期。首先,定位到日期输入框并移除`readonly`属性,然后使用`sendKeys`方法输入日期。这样,即使输入框设置了`readonly`,也能成功处理日期控件。

1.简介

  理想很丰满现实很骨感,在应用selenium实现web自动化时,经常会遇到处理日期控件点击问题,手工很简单,可以一个个点击日期控件选择需要的日期,但自动化执行过程中,完全复制手工这样的操作就有点难了。宏哥上一篇已经讲解了如何处理日历时间控件,但是对于第一种方法可能会遇到输入框是readonly的情况,那么第一种方法就不适用了,但是只要我们稍微的变通地处理一下,就又可以使用了。

2.问题

宏哥第一种方法地思路就是把它当做输入框,直接输入日期即可,想法是很美好的,但是有时候实行起来却不执行,这个时候我们就要仔细去看看前端的代码了,代码如下:

<div class="col-lg-3 form-input">

 <input id="createTime" class="form-control" type="text" readonly="readonly" name="tatsudoDate" onclick="WdatePicker()" aria-required="true">

</div>

从上边的代码可以看出属性readonly人家根本不允许你输入,你就行不通了。

3.想法

既然这样了,我们就稍微变通一下,不要一条道走到黑。这个时候我们可以移除readonly的属性,问题就轻轻松松解决了,代码如下:

String js = "document.getElementById('createTime').removeAttribute('readonly')"; // 原生js,移除属性

((JavascriptExecutor)driver).executeScript(js); //将driver强制转换为JavascriptExecutor类型

driver.findElement(By.id("createTime")).sendKeys("2016-08-24"); //输入日期

4.注意

代码里面一定要记得导入这个方法(一般代码编辑器eclipse都会报错提示)虽然有提示,但是宏哥在这里还是提示一下,不要导错包了。:

import org.openqa.selenium.JavascriptExecutor;

5.项目实战

网上找了半天也没有找到这样的例子,以前12306的日历是这种。最近升级了,已经不是这种了。不找了索性宏哥自己在本地做一个这样的小demo给小伙伴或者童鞋们来演示一下。

注:本文演示的数据大家可以在公众号后台回复 宏哥38,在java+selenium->38 文件夹领取。

5.1代码准备

5.1.1前端HTML代码

前端HTML代码如下:

<!DOCTYPE html>

<html xmlns="http://www.w3.org/1999/xhtml">

<head>

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

   <title></title>

   <script src="dateJs.js"></script>

   <link rel="stylesheet" type="text/css" href="date.css">  

</head>

<body>

   <div id="wrapper" style="position: relative;top: 100px;left:600px;">

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

       <input type="text" id="Dateinput" readonly=""/>

       <div class="calendar" id="calender" style="display: none;">

       </div>

   </div>

</body>

</html>

5.1.2CSS样式

HTML滑块CSS样式代码如下:

* {

   margin: 0;

   padding: 0;

}


body {

   font-size: 13px;

}


.calendar {

   width: 330px;

}


.calendar .title {

   position: relative;

   width: 100%;

   height: 30px;

   line-height: 30px;

   background: #17a4eb;

}


.title div {

   position: absolute;

}


.prev {

   left: 10px;

}


.now {

   left: 40%;

}


.next {

   right: 10px;

}


input {

   height: 30px;

   width: 326px;

}


table {

   width: 100%;

   border-collapse: collapse;

}


table th {

   border: 1px solid #ccc;

}


table td {

   text-align: center;

   border: 1px solid #ccc;

}


.red {

   background-color: #a1cbdb;

}


.blue {

   background-color: #e4e3e3;

}


.button1 {

   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;

   text-decoration: none;

   color: white;

}


#myAnchor {

   text-decoration: none;

   color: white;

}

5.1.3日历JS

日历JS代码如下:

window.onload = function () {

   //获取日期 输入框

   var oInput = document.getElementById('Dateinput');

   //获取日历

   var oCalender = document.getElementById('calender');

   //获取当前日期

   var oDate = new Date();

   //获取当年 年

   var year = oDate.getFullYear();

   //获取当前 月

   var month = oDate.getMonth() + 1;


   //日历框不能重复创建

   var flag = false;

   //日期输入框 获取焦点时 加载日历

   oInput.onfocus = function () {

       showDate(year, month);

   }


   //显示日历

   function showDate(year, month) {

       if (false == flag) {

           //1.日历标题

           var oTitle = document.createElement('div');

           oTitle.className = 'title';


           //1.1日历标题文本

           var prevM = 0;

           var nextM = 0;


           prevM = month - 1;

           nextM = month + 1;


           //当月份为1时 上一个月为12

           if (month == 1) {

               prevM = 12;

           }//当月份为12时 下一个月为1

           else if (month == 12) {

               nextM = 1;

           }


           var titleHtml = "";

           titleHtml += '<div class="prev" id="prev"><span>';

           titleHtml += prevM + '</span>月</div>';

           titleHtml += '<div class="now">';

           titleHtml += '<span class="span">';

           titleHtml += year;

           titleHtml += '</span>年';

           titleHtml += '<span class="span">' + month;

           titleHtml += '</span>月</div>';

           titleHtml += '<div class="next" id="next"><span>';

           titleHtml += nextM + '</span>月</div>';


           oTitle.innerHTML = titleHtml;

           //将日历标题 拼接到日历

           oCalender.appendChild(oTitle);


           //1.2获取日历 表头元素(以便添加事件)

           var oSpans = oCalender.getElementsByTagName('span');

           var prevMonth = oSpans[0];

           var nextMonth = oSpans[3];

           var nowMonth = oSpans[2];

           var nowYear = oSpans[1];


           //2.创建星期 表头

           var otable = document.createElement('table');

           var othead = document.createElement('thead');

           var otr = document.createElement('tr');


           //2.1表头内容填充

           var arr = ['日', '一', '二', '三', '四', '五', '六'];

           for (var i = 0; i < arr.length; i++) {

               //创建th

               var oth = document.createElement('th');

               oth.innerHTML = arr[i];

               otr.appendChild(oth);

           }


           //2.2将表头加入到日历

           othead.appendChild(otr);

           otable.appendChild(othead);

           oCalender.appendChild(otable);


           //3.添加 当前日历 全部日期

           //3.1.先获得当期月 有多少天

           var dayNum = 0;

           if (month == 1 || month == 3 || month == 5 || month == 7 || month == 8 || month == 10 || month == 12) {

               dayNum = 31;

           } else if (month == 4 || month == 6 || month == 9 || month == 11) {

               dayNum = 30;

           } else if (month == 2 && isLeapYear(year)) {

               dayNum = 29;

           } else {

               dayNum = 28;

           }


           //3.2.创建 6行7列 日期容器

           var otbody = document.createElement('tbody');

           for (var i = 0; i < 6; i++) {

               var otr = document.createElement('tr');

               for (var j = 0; j < 7; j++) {

                   var otd = document.createElement('td');

                   otr.appendChild(otd);

               }

               otbody.appendChild(otr);

           }

           otable.appendChild(otbody);


           //3.3获得 1号对应的是星期几

           //3.3.1.将当月1号赋值给日期变量

           oDate.setFullYear(year);

           //注意 js日期的月份是从0 开始计算

           oDate.setMonth(month - 1);

           oDate.setDate(1);


           //3.3.2.计算1号在第一行日期容器中的位置,依次给日期容器填充内容

           //注意 js中 getDay方法是获取当前日期是星期几

           var week = oDate.getDay();

           var otds = oCalender.getElementsByTagName('td');

           for (var i = 0; i < dayNum; i++) {

               otds[i + week].innerHTML = i + 1;

           }



           //让当前日期显示红色、后面的显示蓝色

           showColor(otds);

           //给左右月份绑定点击事件

           monthEvent();

           //判断最后一行是否全为空

           lastTr(otds);

           flag = true;

           document.getElementById('calender').style.display = "block";

       }

   }


   //判断是否是闰年

   function isLeapYear(year) {

       if (year % 100 == 0 && year % 400 == 0) {

           return true;

       } else if (year % 100 != 0 && year % 4 == 0) {

           return true;

       } else {

           return false;

       }

   }


   //判断日期容器最后一行是否有值

   function lastTr(otds) {

       var flag = true;

       for (var i = 35; i < 42; i++) {

           if (otds[i].innerHTML != '') {

               flag = false;

           }

       }

       //全是空的

       if (flag) {

           for (var i = 35; i < 42; i++) {

               otds[i].style.display = 'none';

           }

       }

   }


   //当前日期显示红色、前面的显示灰色

   function showColor(otds) {

       //当前日期

       var nowday = new Date().getDate();

       var nowyear = new Date().getFullYear();

       var nowmonth = new Date().getMonth();


       var oCalendar = document.getElementById("calender");

       ospans = oCalendar.getElementsByTagName('span');

       var contralYear = ospans[1].innerHTML;

       var contralMonth = ospans[2].innerHTML;


       var oindex = 0;

       for (var i = 0; i < otds.length; i++) {

           if (nowday == otds[i].innerHTML && nowyear == contralYear && nowmonth + 1 == contralMonth) {

               otds[i].className = 'red';

               oindex = i;

           }

       }

   }


   //给左右月份绑定点击事件

   function monthEvent() {

       var oCalendar = document.getElementById("calender");

       var prevDiv = document.getElementById("prev");

       var nextDiv = document.getElementById("next");


       var prevMonth = prevDiv.getElementsByTagName("span");

       var nextMonth = nextDiv.getElementsByTagName("span");


       prevDiv.onclick = function () {

           flag = false;

           oCalendar.innerHTML = '';

           showDate(year, parseInt(prevMonth[0].innerHTML));

       }


       nextDiv.onclick = function () {

           flag = false;

           oCalendar.innerHTML = '';

           showDate(year, parseInt(nextMonth[0].innerHTML));

       }


   }

}

6.自动化代码实现

6.1代码设计

6.2参考代码

package lessons;


import org.openqa.selenium.By;

import org.openqa.selenium.JavascriptExecutor;//注意不要倒错包

import org.openqa.selenium.WebDriver;

import org.openqa.selenium.chrome.ChromeDriver;


/**

* @author 北京-宏哥

*

* 《手把手教你》系列技巧篇(三十八)-java+ selenium自动化测试-日历时间控件-下篇(详解教程)

*

* 2021年10月31日

*/

public class calendar {


   public static void main(String[] args) {

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

       WebDriver driver =new ChromeDriver();

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

       try {

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

           Thread.sleep(5000);

           //执行方式

           JavascriptExecutor jsExecutor = (JavascriptExecutor) driver;

           String js = "document.getElementById('Dateinput').removeAttribute('readonly')";

           jsExecutor.executeScript(js);//执行js,将readonly属性去掉后就可以写入日期

           driver.findElement(By.id("Dateinput")).clear();//写入前清除数据

           driver.findElement(By.id("Dateinput")).sendKeys("2021-11-11");//写入期望日期

           Thread.sleep(5000);

       } catch (Exception e) {

           e.printStackTrace();

       }finally {

           System.out.println("执行结束,关闭浏览器!提前祝大家光棍节快乐!!!");

           driver.quit();

       }

   }

}

6.3运行代码

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

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

7.小结

好了,时间不早了,今天就分享到这里,感谢大家耐心的阅读,这两篇其实是为后边文章的JavaScript的调用做一下铺垫和入门。


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

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


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

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

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

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

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

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

Pycharm工具基础使用教程

相关文章
java.lang.NullPointerExceptionMybatisPlus出现,测试,java.lang.NullPointe,空指针异常,public方法少写了一个字段,没加注解
java.lang.NullPointerExceptionMybatisPlus出现,测试,java.lang.NullPointe,空指针异常,public方法少写了一个字段,没加注解
|
2天前
|
XML Java 测试技术
《手把手教你》系列基础篇(八十七)-java+ selenium自动化测试-框架设计基础-Log4j 2实现日志输出-上篇(详解教程)
【7月更文挑战第5天】Apache Log4j 2是一个日志框架,它是Log4j的升级版,提供了显著的性能提升,借鉴并改进了Logback的功能,同时修复了Logback架构中的问题。Log4j2的特点包括API与实现的分离,支持SLF4J,自动重新加载配置,以及高级过滤选项。它还引入了基于lambda表达式的延迟评估,低延迟的异步记录器和无垃圾模式。配置文件通常使用XML,但也可以是JSON或YAML,其中定义了日志级别、输出目的地(Appender)和布局(Layout)。
|
2天前
|
Java 测试技术 持续交付
如何在Java中实现自动化测试和集成测试
如何在Java中实现自动化测试和集成测试
|
2天前
|
Java 测试技术 持续交付
Java中的单元测试与集成测试最佳实践
Java中的单元测试与集成测试最佳实践
|
2天前
|
IDE Java 测试技术
使用Java实现单元测试:JUnit教程
使用Java实现单元测试:JUnit教程
|
2天前
|
敏捷开发 Java jenkins
实现Java中的自动化测试策略和工具推荐
实现Java中的自动化测试策略和工具推荐
|
16天前
|
Java 测试技术 Python
《手把手教你》系列基础篇(八十)-java+ selenium自动化测试-框架设计基础-TestNG依赖测试-番外篇(详解教程)
【6月更文挑战第21天】本文介绍了TestNG中测试方法的依赖执行顺序。作者通过一个实际的自动化测试场景展示了如何设计测试用例:依次打开百度、搜索“selenium”、再搜索“selenium+java”。代码示例中,`@Test`注解的`dependsOnMethods`属性用于指定方法间的依赖,确保执行顺序。如果不设置依赖,TestNG会按方法名首字母排序执行。通过运行代码,验证了依赖关系的正确性。
38 4
|
3天前
|
XML 测试技术 数据格式
《手把手教你》系列基础篇(八十五)-java+ selenium自动化测试-框架设计基础-TestNG自定义日志-下篇(详解教程)
【7月更文挑战第3天】TestNG教程展示了如何自定义日志记录。首先创建一个名为`TestLog`的测试类,包含3个测试方法,其中一个故意失败以展示日志。使用`Assert.assertTrue`和`Reporter.log`来记录信息。接着创建`CustomReporter`类,继承`TestListenerAdapter`,覆盖`onTestFailure`, `onTestSkipped`, 和 `onTestSuccess`,在这些方法中自定义日志输出。
21 6
|
3天前
|
Java 测试技术 Apache
《手把手教你》系列基础篇(八十六)-java+ selenium自动化测试-框架设计基础-Log4j实现日志输出(详解教程)
【7月更文挑战第4天】Apache Log4j 是一个广泛使用的 Java 日志框架,它允许开发者控制日志信息的输出目的地、格式和级别。Log4j 包含三个主要组件:Loggers(记录器)负责生成日志信息,Appenders(输出源)确定日志输出的位置(如控制台、文件、数据库等),而 Layouts(布局)则控制日志信息的格式。通过配置 Log4j,可以灵活地定制日志记录行为。
18 4
|
13天前
|
Java 测试技术 Python
《手把手教你》系列基础篇(八十一)-java+ selenium自动化测试-框架设计基础-TestNG如何暂停执行一些case(详解教程)
【6月更文挑战第22天】本文介绍了如何在TestNG中不执行特定测试用例。当部分模块未准备好时,可以通过以下方式暂停测试:③使用`@Test(enabled=false)`注解来禁用测试用例。作者提供了一个Java Selenium自动化测试的示例,展示如何通过修改`enabled`参数控制测试方法的执行。代码中,`testSearch2()`方法被禁用,因此在测试运行时不执行。文章还包含了测试报告和执行过程的截图。
39 7

热门文章

最新文章