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

相关文章
|
1月前
|
XML Java Maven
在 Cucumber 测试中自动将 Cucumber 数据表映射到 Java 对象
在 Cucumber 测试中自动将 Cucumber 数据表映射到 Java 对象
50 7
|
3月前
|
Java Devops 持续交付
探索Java中的Lambda表达式:简化代码,提升效率DevOps实践:持续集成与部署的自动化之路
【8月更文挑战第30天】本文深入探讨了Java 8中引入的Lambda表达式如何改变了我们编写和管理代码的方式。通过简化代码结构,提高开发效率,Lambda表达式已成为现代Java开发不可或缺的一部分。文章将通过实际例子展示Lambda表达式的强大功能和优雅用法。
|
3月前
|
XML Java 测试技术
Selenium WebDriver自动化测试(基础篇):不得不掌握的Java基础
关于Selenium WebDriver自动化测试的Java基础篇,涵盖了Java的变量、数据类型、字符串操作、运算符、流程控制、面向对象编程、关键字用法、权限修饰符、异常处理和IO流等基础知识点,为进行自动化测试提供了必要的Java语言基础。
99 1
|
3月前
|
Java 持续交付 项目管理
Maven是一款基于Apache许可的项目管理和构建自动化工具,在Java开发中极为流行。
Maven是一款基于Apache许可的项目管理和构建自动化工具,在Java开发中极为流行。它采用项目对象模型(POM)来描述项目,简化构建流程。Maven提供依赖管理、标准构建生命周期、插件扩展等功能,支持多模块项目及版本控制。在Java Web开发中,Maven能够自动生成项目结构、管理依赖、自动化构建流程并运行多种插件任务,如代码质量检查和单元测试。遵循Maven的最佳实践,结合持续集成工具,可以显著提升开发效率和项目质量。
52 1
|
3月前
|
运维 Java API
探索Java中的Lambda表达式自动化运维的魔法:如何利用Python脚本提升效率
【8月更文挑战第29天】Lambda表达式是Java 8中引入的一个新特性,它允许我们将功能作为方法参数,或者代码作为数据来处理。在这篇文章中,我们将深入探讨Java中的Lambda表达式,包括它的语法、使用场景以及如何在实际编程中应用它。我们将通过一些简单的示例来演示Lambda表达式的强大功能和灵活性,让你更好地理解和掌握这一新特性。
|
4月前
|
数据采集 安全 Java
Java Selenium WebDriver:代理设置与图像捕获
Java Selenium WebDriver:代理设置与图像捕获
|
3月前
|
数据采集 SQL 前端开发
Java SpringBoot自动化网页爬虫项目
这是一个基于Java Spring Boot的自动化网页爬虫平台,采用图形化界面定义爬虫流程,无需编写代码。该平台高度灵活且可配置,支持Xpath、JsonPath、CSS选择器及正则表达式等多种提取方式,兼容JSON、XML和二进制格式,并支持通过代理服务器访问。它还具备自动管理Cookie、保存数据至数据库或文件、自定义函数和SQL脚本等功能,同时集成了任务监控和日志记录系统。此外,平台支持HTTP接口调用和动态网页抓取,可通过Selenium模拟真实浏览器行为。用户可通过直观的操作界面轻松完成复杂的数据抓取任务。
|
4月前
|
测试技术 API Android开发
《手把手教你》系列基础篇(九十七)-java+ selenium自动化测试-框架设计篇-Selenium方法的二次封装和页面基类(详解教程)
【7月更文挑战第15天】这是关于自动化测试框架中Selenium API二次封装的教程总结。教程中介绍了如何设计一个支持不同浏览器测试的页面基类(BasePage),该基类包含了对Selenium方法的二次封装,如元素的输入、点击、清除等常用操作,以减少重复代码。此外,页面基类还提供了获取页面标题和URL的方法。
103 2
|
3月前
|
jenkins Java 持续交付
自动化魔法:用Jenkins打造Java项目的持续部署流水线
【8月更文挑战第13天】在软件开发中,自动化部署是提高效率与减少错误的关键。Jenkins作为一款强大的持续集成工具,支持Java项目的自动化构建、测试与部署。通过配置Jenkins及其丰富的插件生态(如Git和Maven插件),可实现从代码提交到上线的全自动化流程。此流程包括从GitHub自动拉取代码、使用Maven构建项目,并通过如`mvn clean install`命令执行构建,最后利用插件如“Publish Over SSH”将制品部署至远程服务器。此外,还可配置邮件通知等后处理动作确保发布的稳定可靠。借助Jenkins,开发者能显著加速软件交付周期,同时减少手动操作带来的风险。
137 0
|
4月前
|
Web App开发 XML Java
《手把手教你》系列基础篇(九十六)-java+ selenium自动化测试-框架之设计篇-跨浏览器(详解教程)
【7月更文挑战第14天】这篇教程介绍了如何使用Java和Selenium构建一个支持跨浏览器测试的自动化测试框架。设计的核心是通过读取配置文件来切换不同浏览器执行测试用例。配置文件中定义了浏览器类型(如Firefox、Chrome)和测试服务器的URL。代码包括一个`BrowserEngine`类,它初始化配置数据,根据配置启动指定的浏览器,并提供关闭浏览器的方法。测试脚本`TestLaunchBrowser`使用`BrowserEngine`来启动浏览器并执行测试。整个框架允许在不同浏览器上运行相同的测试,以确保兼容性和一致性。
93 3