JavasSript实现秒转换为“天时分秒”控件和TDD测试方法应用
背景
時(shí)間累計(jì)值,在頂層一般以秒為計(jì)算單位,?所以到頁面上如果直接顯示xx秒,?如果秒的值很大,?則用戶得不到直觀的感受,?到底有多長時(shí)間,
在日長生活中,?人們以天?時(shí)?分?秒為單位來記錄時(shí)間累計(jì)值,?這樣更容易為人們接受,?提高易用性。
本文就為了解決這個(gè)問題,?在頁面控件?和?累計(jì)值秒?之間建立轉(zhuǎn)換,?提供顯示和配置。
設(shè)計(jì)思路
將秒轉(zhuǎn)換為 天?時(shí)?分?秒?控件,?此處控件為下拉框,??從右到左,?分為四級(jí),?每一級(jí)的單位權(quán)值遞減,
天?的可選值?為? 0 - +無窮, 1天=86400秒
時(shí)?的可選值?為 0 - 23, 1時(shí)=3600秒
分?的可選值為 0-59, 1分=60秒
秒?的可選值為 0-59
?
時(shí)間控件支持的范圍?range=[x, y],? y>=x>=0
但是,需要注意當(dāng)上一級(jí)單位下拉框選擇為邊界值時(shí)候,?則下一級(jí)下拉框中,?可選項(xiàng)可能不能填滿,?例如
range = [0, 60],??分可選值為 0-1,?當(dāng)分選擇為 0時(shí)候,?秒可選值為 0-59,?當(dāng)分選擇為1時(shí)候,?秒可選值為0
?
同時(shí)對(duì)于最大值達(dá)不到的?單位控件,?則需要隱藏。
?
時(shí)間控件?靜態(tài)包括?天?時(shí)?分?秒?四個(gè)子控件(四個(gè)下拉框),
控件加載時(shí)候,?根據(jù)range初始化時(shí)間控件,?此時(shí)該最大值達(dá)不到的單位控件需要隱藏掉, 各個(gè)子控件填充可選內(nèi)容,? 此過程記錄為??InitTime
下一級(jí)控件需要根據(jù)上一級(jí)控件的當(dāng)前值,?來填充可選值,?此功能實(shí)現(xiàn)需要在上一級(jí)的控件的?change事件中實(shí)現(xiàn),?并且按照級(jí)別遞歸觸發(fā)change。
開發(fā)過程
寫完初始化函數(shù),?和天?時(shí)?分?的change事件,
書寫TDD相關(guān)的測(cè)試代碼,?將各個(gè)用例寫入測(cè)試代碼,?則拉起一個(gè)測(cè)試網(wǎng),?調(diào)試過程中,?此網(wǎng)可以一步一步添加,
在添加過程中, 遇到問題, 可會(huì)修改時(shí)間控件代碼,??修改完畢后,?則添加下一個(gè)用例,
直到添加調(diào)試完所有你認(rèn)可的測(cè)試用例。
?
這樣開發(fā)后的控件,?經(jīng)過足夠多的用例檢驗(yàn),?質(zhì)量可以保證。
而且為以后的維護(hù)打下基礎(chǔ),?如果后期需要微調(diào)此控件,?則微調(diào)后,?通過微調(diào)自己的TDD代碼,?并且也需要通過本次開發(fā)的測(cè)試用例代碼,?保證質(zhì)量的繼承性。
效果
代碼如下:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml"> <head runat="server"><title>Second2DHMS</title><script src="jquery.js" type="text/javascript"></script><meta http-equiv="content-type" content="text/html; charset=UTF-8" /> </head> <body><div id="TimeScalar"></div><script> console.log = console.log || {}/******************************************************************************* Description: Changes: *******************************************************************************/ function Second2DHMS(num) {var s = num%60;num=parseInt(num/60);var m = num%60;num = parseInt(num/60);var h = num%24;num = parseInt(num/24);var d = num;//console.log(d+'天'+h+'時(shí)'+m+'分'+s+'秒')return {day: d,hour: h,minute: m,second: s} }function FillSelectOption(controlId, min, max) {$("#"+controlId).empty();//緩存提速var domCache = [];for (var i = min; i <= max; i++){domCache.push("<option title='" +i+ "' value='" +i+ "'>"+i+"</option>");}$("#"+controlId).append(domCache.join()); }/* 天控件 值選中后,改變時(shí)控件可選值 */ $("#TimeScalar").on("change", "#Day", function(event){var day = $(this).val();var maxDay = Math.floor(range.max / 86400);var maxDayRemain = range.max % 86400;var maxHour = Math.floor(maxDayRemain / 3600);var minDay = Math.floor(range.min / 86400);var minDayRemain = range.min % 86400;var minHour = Math.floor(minDayRemain / 3600);/* 天值 最大和最小 都是一個(gè)值例如 {min:4294967294, max:4294967295}49710天6時(shí)28分15秒49710天6時(shí)28分14秒*/if ( minDay == maxDay ){FillSelectOption("Hour", minHour, maxHour);$(this).data("cursor", "MinMax");}/* 天值 在 最大 和 最小 之間 */else if ( day > minDay && day < maxDay ){FillSelectOption("Hour", 0, 23);$(this).data("cursor", "Middle");}/* 天值 為最大 */else if ( day == maxDay ){FillSelectOption("Hour", 0, maxHour);$(this).data("cursor", "Max");}/* 天值 為最小 */else if ( day == minDay ){FillSelectOption("Hour", minHour, 23);$(this).data("cursor", "Min");}else{}/* 更新分控件可選值,一旦選擇了最大值,這些控件范圍有可能是部分可選項(xiàng),如果天選擇不為最大值,則這些控件需要包括全部可選項(xiàng)。*/$("#Hour").change();event.stopPropagation(); });/* 時(shí)控件 值選中后,改變分控件可選值 */ $("#TimeScalar").on("change", "#Hour", function(event){var hour = $(this).val();var maxDayRemain = range.max % 86400;var maxHour = Math.floor(maxDayRemain / 3600);var maxHourRemain = range.max % 3600;var maxMinute = Math.floor(maxHourRemain / 60);var minDayRemain = range.min % 86400;var minHour = Math.floor(minDayRemain / 3600);var minHourRemain = range.min % 3600;var minMinute = Math.floor(minHourRemain / 60);/* 時(shí)值 最大和最小 都是一個(gè)值例如 {min:4294967294, max:4294967295}49710天6時(shí)28分15秒49710天6時(shí)28分14秒*/if ( $("#Day").data("cursor") == "MinMax"&& minHour == maxHour ){FillSelectOption("Minute", minMinute, maxMinute);$(this).data("cursor", "MinMax");}else if ( ($("#Day").data("cursor") == "Max"|| $("#Day").data("cursor") == "MinMax" )&& hour == maxHour ){FillSelectOption("Minute", 0, maxMinute);$(this).data("cursor", "Max");}else if ( ($("#Day").data("cursor") == "Min"|| $("#Day").data("cursor") == "MinMax" )&& hour == minHour ){FillSelectOption("Minute", minMinute, 59);$(this).data("cursor", "Min");}else{FillSelectOption("Minute", 0, 59);$(this).data("cursor", "Middle");}/* 更新秒控件可選值,一旦選擇了最大值,這些控件范圍有可能是部分可選項(xiàng),如果天選擇不為最大值,則這些控件需要包括全部可選項(xiàng)。*/$("#Minute").change();event.stopPropagation(); });/* 分控件 值選中后,改變秒控件可選值 */ $("#TimeScalar").on("change", "#Minute", function(event){var minute = $(this).val();var maxHourRemain = range.max % 3600;var maxMinute = Math.floor(maxHourRemain / 60);var maxMinuteRemain = range.max % 60;var maxSecond = Math.floor(maxMinuteRemain / 1);var minHourRemain = range.min % 3600;var minMinute = Math.floor(minHourRemain / 60);var minMinuteRemain = range.min % 60;var minSecond = Math.floor(minMinuteRemain / 1);/* 分值 最大和最小 都是一個(gè)值例如 {min:4294967294, max:4294967295}49710天6時(shí)28分15秒49710天6時(shí)28分14秒*/if ( $("#Day").data("cursor") == "MinMax"&& $("#Hour").data("cursor") == "MinMax" && minMinute == maxMinute ){FillSelectOption("Second", minSecond, maxSecond);}else if ( ($("#Day").data("cursor") == "Max"|| $("#Day").data("cursor") == "MinMax" )&& ( $("#Hour").data("cursor") == "Max"|| $("#Hour").data("cursor") == "MinMax" )&& minute == maxMinute ){FillSelectOption("Second", 0, maxSecond);}else if ( ($("#Day").data("cursor") == "Min"|| $("#Day").data("cursor") == "MinMax" )&& ( $("#Hour").data("cursor") == "Min"|| $("#Hour").data("cursor") == "MinMax" )&& minute == minMinute ){FillSelectOption("Second", minSecond, 59);}else{FillSelectOption("Second", 0, 59);}event.stopPropagation(); });function InitTimeScalar(range) {// console.log('--------------- init time ['+range.min+''+range.max+'] -------');// Second2DHMS(range.min)// Second2DHMS(range.max)/* 控件初始化 */$("#TimeScalar").empty();$("#TimeScalar").append('\<select id="Day"></select><label for="Day">天</label>\<select id="Hour"></select><label for="Hour">時(shí)</label>\<select id="Minute"></select><label for="Minute">分</label>\<select id="Second"></select><label for="Second">秒</label>');var minDay = Math.floor(range.min / 86400);var maxDay = Math.floor(range.max / 86400);/* 填充天控件可選項(xiàng) */FillSelectOption("Day", minDay, maxDay);/* 觸發(fā)天控件change,初始化填充時(shí)分秒控件可選項(xiàng) */$("#Day").change();/* 如果最大單位未達(dá)到,則隱藏掉對(duì)應(yīng)控件 */var maxDay = Math.floor(range.max / 86400);if ( maxDay == 0 ){$("#Day").hide();$("label[for='Day']").hide();var maxHour = Math.floor(range.max / 3600);if ( maxHour == 0 ){$("#Hour").hide();$("label[for='Hour']").hide();var maxMinute = Math.floor(range.max / 60);if ( maxMinute == 0 ){$("#Minute").hide();$("label[for='Minute']").hide();}}} }function SetTimeControlValue(second) {var dhmsJson = Second2DHMS(second);$("#Day").val(dhmsJson.day);$("#Day").change();$("#Hour").val(dhmsJson.hour);$("#Hour").change();$("#Minute").val(dhmsJson.minute);$("#Minute").change();$("#Second").val(dhmsJson.second); }function GetTimeControlValue() {var d = $("#Day").val(); var h = $("#Hour").val();var m = $("#Minute").val();var s = $("#Second").val();var totolSec = d * 86400+ h * 3600+ m * 60+ s * 1;return totolSec; }/******************************************************************************* Description: 測(cè)試用例 Changes: *******************************************************************************/ /* 考慮使用jsunit整個(gè)控件考慮使用模塊化思想*/ function TestSetGet(second, bResult) {//console.log("----- test set time value("+second+") --------" ); SetTimeControlValue(second);var realSec = GetTimeControlValue();var bRealResult = ( realSec == second );if ( bResult != bRealResult ){console.warn("!!!! second("+second+") test failed! realSec="+realSec);}else{console.log("second("+second+") test success!");} }/* 一般范圍測(cè)試: 1、頁面載入,沒有后臺(tái)賦值, 查看各個(gè)控件可選范圍:天 0-49710時(shí) 0-23分 0-59秒 0-59 2、MAX測(cè)試:a. 選擇天為 49710, 查看時(shí)選擇范圍為 0-6b. 選擇時(shí)為 6, 查看分選擇范圍為 0-28c. 選擇分為 28, 查看秒選擇范圍為 0-15, 選擇秒15 OKd. 再次切換分為 27, 查看秒 可選范圍 為 0-59e. 再次切換時(shí)為 5, 查看分 可選值為 0-59f. 再次切換天為 49709,查看時(shí) 可選值為 0-2349710天6時(shí)28分15秒 */ var range = {min:0, max:4294967295} InitTimeScalar(range);TestSetGet(4294967295, true); TestSetGet(4294967296, false); TestSetGet(100, true); TestSetGet(0, true); TestSetGet(-1, false);/* range相差1s測(cè)試范圍為 {min:4294967294, max:4294967295}49710天6時(shí)28分15秒49710天6時(shí)28分14秒查看各個(gè)控件可選值天 - 49710時(shí) - 6分 - 28秒 - 14-15 */ var range = {min:4294967294, max:4294967295} InitTimeScalar(range);TestSetGet(4294967295, true); TestSetGet(4294967296, false); TestSetGet(4294967294, true); TestSetGet(4294967293, false);/* range相差1分鐘測(cè)試范圍 {min:4294967235, max:4294967295}49710天6時(shí)28分15秒49710天6時(shí)27分15秒查看各個(gè)控件可選值天 - 49710時(shí) - 6分 - 27-28秒 - 15-59 選擇分為 27秒 - 0-15 選擇分為 28*/ var range = {min:4294967235, max:4294967295} InitTimeScalar(range);TestSetGet(4294967295, true); TestSetGet(4294967296, false); TestSetGet(4294967235, true); TestSetGet(4294967234, false);/* range相差1小時(shí)測(cè)試范圍 {min:4294963695, max:4294967295}49710天6時(shí)28分15秒49710天5時(shí)28分15秒查看各個(gè)控件可選值天 - 49710時(shí) - 5-6分 - 28-59 選擇時(shí)為 5分 - 0-28 選擇時(shí)為 6秒 - 15-59 選擇分為 28,時(shí)為5秒 - 0-59 選擇分為 29,時(shí)為5秒 - 0-15 選擇分為 28, 時(shí)為6秒 - 0-59 選擇分為 27, 時(shí)為6*/ var range = {min:4294963695, max:4294967295} InitTimeScalar(range);TestSetGet(4294967295, true); TestSetGet(4294967296, false); TestSetGet(4294963695, true); TestSetGet(4294963694, false);/* range相差1天測(cè)試范圍 {min:4294880895, max:4294967295}49710天6時(shí)28分15秒49709天6時(shí)28分15秒查看各個(gè)控件可選值天 - 49709-49710時(shí) - 6-23 選擇天為49709時(shí) - 0-6 選擇天為49710選擇天為49709,時(shí)為7, 查看分秒范圍都為 0-59選擇天為49710,時(shí)為5, 查看分秒范圍都為 0-59*/ var range = {min:4294880895, max:4294967295} InitTimeScalar(range);TestSetGet(4294967295, true); TestSetGet(4294967296, false); TestSetGet(4294880895, true); TestSetGet(4294880894, false);/* range最大值為1天測(cè)試,查看最大和最小值如下可選1天0時(shí)0分0秒0天0時(shí)0分0秒*/ var range = {min:0, max:86400} InitTimeScalar(range);TestSetGet(86400, true); TestSetGet(86401, false); TestSetGet(0, true); TestSetGet(-1, false);/* range最大值不足1天測(cè)試天控件未顯示,時(shí)分秒最大最小值可選如下0天23時(shí)59分59秒0天0時(shí)0分0秒*/ var range = {min:0, max:86399} InitTimeScalar(range);TestSetGet(86399, true); TestSetGet(86400, false); TestSetGet(0, true); TestSetGet(-1, false);/* range最大值為1小時(shí)時(shí)分秒最大最小值可選如下0天1時(shí)0分0秒0天0時(shí)0分0秒*/ var range = {min:0, max:3600} InitTimeScalar(range);TestSetGet(3600, true); TestSetGet(3601, false); TestSetGet(0, true); TestSetGet(-1, false);/* range最大值為 3599時(shí)分秒最大最小值可選如下0天0時(shí)59分59秒0天0時(shí)0分0秒*/ var range = {min:0, max:3599} InitTimeScalar(range);TestSetGet(3599, true); TestSetGet(3600, false); TestSetGet(0, true); TestSetGet(-1, false);/* range最大值 1分鐘 0天0時(shí)1分0秒0天0時(shí)0分0秒 */ var range = {min:0, max:60} InitTimeScalar(range);TestSetGet(60, true); TestSetGet(61, false); TestSetGet(0, true); TestSetGet(-1, false);/* range最大值 590天0時(shí)0分59秒0天0時(shí)0分0秒 */ var range = {min:0, max:59} InitTimeScalar(range);TestSetGet(59, true); TestSetGet(60, false); TestSetGet(0, true); TestSetGet(-1, false); TestSetGet(59, true);</script> </body> </html>?
在火狐上運(yùn)行后,?控制臺(tái)上打印如下:
?
引申
TDD屬于單元測(cè)試范疇,?除了自己寫TDD測(cè)試函數(shù),?也可以借助測(cè)試框架 XUnit
js有對(duì)應(yīng)的 JSUnit
1、?JsUnit??官網(wǎng) http://www.jsunit.net/
github上項(xiàng)目(若干年前, 已經(jīng)不再維護(hù),?替換品為 Jasmine)
https://github.com/pivotal/jsunit
使用方法介紹:
http://www.cnblogs.com/youcai/archive/2012/02/10/2345689.html
與其比較:??JsUnit適合較大測(cè)試對(duì)象,?測(cè)試結(jié)果比較直觀,??本控件規(guī)模小,?就不用此工具了。
此工具,?對(duì)于本文對(duì)象,?測(cè)試用例,?需要針對(duì)每種測(cè)試range,?單獨(dú)開一個(gè)html,?然后組成一個(gè)?suite,?比較麻煩。
?
2、 https://github.com/jasmine/jasmine
Jasmine is a Behavior Driven Development testing framework for JavaScript. It does not rely on browsers, DOM, or any JavaScript framework. Thus it's suited for websites, Node.js projects, or anywhere that JavaScript can run.
日后研究。
?
3、?QUnit?基于JQuery的測(cè)試框架:
http://qunitjs.com/
對(duì)于本文若干測(cè)試range,?可以容納與一個(gè)js文件中執(zhí)行,?可以后續(xù)嘗試。
QUnit.test( "hello test", function( assert ) { assert.ok( 1 == "1", "Passed!" ); });?
轉(zhuǎn)載于:https://www.cnblogs.com/lightsong/p/4641893.html
總結(jié)
以上是生活随笔為你收集整理的JavasSript实现秒转换为“天时分秒”控件和TDD测试方法应用的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: HDU Senior's Gun (水
- 下一篇: 绝大部分项目都是跟金融创新、互联网、移动