《手把手教你》系列技巧篇(三十八)-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工具基础使用教程

相关文章
|
5天前
|
Java 测试技术 C#
自动化测试之美:从Selenium到Appium
【10月更文挑战第3天】在软件开发的海洋中,自动化测试如同一艘航船,引领着质量保证的方向。本文将带你领略自动化测试的魅力,从Web端的Selenium到移动端的Appium,我们将一探究竟,看看这些工具如何帮助我们高效地进行软件测试。你将了解到,自动化测试不仅仅是技术的展示,更是一种提升开发效率和产品质量的智慧选择。让我们一起启航,探索自动化测试的世界!
|
2天前
|
Web App开发 前端开发 JavaScript
探索Python科学计算的边界:利用Selenium进行Web应用性能测试与优化
【10月更文挑战第6天】随着互联网技术的发展,Web应用程序已经成为人们日常生活和工作中不可或缺的一部分。这些应用不仅需要提供丰富的功能,还必须具备良好的性能表现以保证用户体验。性能测试是确保Web应用能够快速响应用户请求并处理大量并发访问的关键步骤之一。本文将探讨如何使用Python结合Selenium来进行Web应用的性能测试,并通过实际代码示例展示如何识别瓶颈及优化应用。
19 5
|
2天前
|
JavaScript 前端开发 测试技术
精通Selenium:从基础到高级的网页自动化测试策略
【10月更文挑战第6天】随着Web应用变得越来越复杂,手动进行功能和兼容性测试变得既耗时又容易出错。自动化测试因此成为了现代软件开发不可或缺的一部分。Selenium是一个强大的工具集,它支持多种编程语言(包括Python),允许开发者编写脚本来模拟用户与Web页面的交互。本文将带领读者从Selenium的基础知识出发,逐步深入到高级的应用场景,通过丰富的代码示例来展示如何高效地进行网页自动化测试。
15 5
|
1天前
|
Java 编译器 Android开发
Kotlin教程笔记(28) -Kotlin 与 Java 混编
Kotlin教程笔记(28) -Kotlin 与 Java 混编
11 3
|
5天前
|
XML Java Maven
在 Cucumber 测试中自动将 Cucumber 数据表映射到 Java 对象
在 Cucumber 测试中自动将 Cucumber 数据表映射到 Java 对象
21 7
|
6天前
|
Web App开发 IDE 测试技术
自动化测试的利器:Selenium 框架深度解析
【10月更文挑战第2天】在软件开发的海洋中,自动化测试犹如一艘救生艇,让质量保证的过程更加高效与精准。本文将深入探索Selenium这一强大的自动化测试框架,从其架构到实际应用,带领读者领略自动化测试的魅力和力量。通过直观的示例和清晰的步骤,我们将一起学习如何利用Selenium来提升软件测试的效率和覆盖率。
|
2天前
|
安全 Java 编译器
Kotlin教程笔记(27) -Kotlin 与 Java 共存(二)
Kotlin教程笔记(27) -Kotlin 与 Java 共存(二)
|
4天前
|
Web App开发 缓存 Linux
高效Selenium测试技巧:轻松控制已开启的浏览器
【10月更文挑战第13天】在进行Selenium测试时,通常会启动新浏览器实例,但有时需要控制已开启的浏览器,以节省时间并更真实地模拟用户行为。这可通过设置Chrome为可远程控制并使用`Remote WebDriver`连接实现。需在启动Chrome时添加`--remote-debugging-port`参数,并通过Python脚本中的`webdriver.Remote`连接至指定端口。此外,还可利用会话ID(Session ID)重新连接浏览器,提高测试灵活性。需要注意浏览器版本兼容性及元素定位稳定性等问题,确保测试准确性和一致性。
|
2天前
|
Java 开发工具 Android开发
Kotlin教程笔记(26) -Kotlin 与 Java 共存(一)
Kotlin教程笔记(26) -Kotlin 与 Java 共存(一)
|
10天前
|
机器学习/深度学习 人工智能 运维
构建高效运维体系:从自动化到智能化的演进
本文探讨了如何通过自动化和智能化手段,提升IT运维效率与质量。首先介绍了自动化在简化操作、减少错误中的作用;然后阐述了智能化技术如AI在预测故障、优化资源中的应用;最后讨论了如何构建一个既自动化又智能的运维体系,以实现高效、稳定和安全的IT环境。
35 4