JavasSript实现秒转换为“天时分秒”控件和TDD测试方法应用
背景
時間累計值,在頂層一般以秒為計算單位,?所以到頁面上如果直接顯示xx秒,?如果秒的值很大,?則用戶得不到直觀的感受,?到底有多長時間,
在日長生活中,?人們以天?時?分?秒為單位來記錄時間累計值,?這樣更容易為人們接受,?提高易用性。
本文就為了解決這個問題,?在頁面控件?和?累計值秒?之間建立轉換,?提供顯示和配置。
設計思路
將秒轉換為 天?時?分?秒?控件,?此處控件為下拉框,??從右到左,?分為四級,?每一級的單位權值遞減,
天?的可選值?為? 0 - +無窮, 1天=86400秒
時?的可選值?為 0 - 23, 1時=3600秒
分?的可選值為 0-59, 1分=60秒
秒?的可選值為 0-59
?
時間控件支持的范圍?range=[x, y],? y>=x>=0
但是,需要注意當上一級單位下拉框選擇為邊界值時候,?則下一級下拉框中,?可選項可能不能填滿,?例如
range = [0, 60],??分可選值為 0-1,?當分選擇為 0時候,?秒可選值為 0-59,?當分選擇為1時候,?秒可選值為0
?
同時對于最大值達不到的?單位控件,?則需要隱藏。
?
時間控件?靜態包括?天?時?分?秒?四個子控件(四個下拉框),
控件加載時候,?根據range初始化時間控件,?此時該最大值達不到的單位控件需要隱藏掉, 各個子控件填充可選內容,? 此過程記錄為??InitTime
下一級控件需要根據上一級控件的當前值,?來填充可選值,?此功能實現需要在上一級的控件的?change事件中實現,?并且按照級別遞歸觸發change。
開發過程
寫完初始化函數,?和天?時?分?的change事件,
書寫TDD相關的測試代碼,?將各個用例寫入測試代碼,?則拉起一個測試網,?調試過程中,?此網可以一步一步添加,
在添加過程中, 遇到問題, 可會修改時間控件代碼,??修改完畢后,?則添加下一個用例,
直到添加調試完所有你認可的測試用例。
?
這樣開發后的控件,?經過足夠多的用例檢驗,?質量可以保證。
而且為以后的維護打下基礎,?如果后期需要微調此控件,?則微調后,?通過微調自己的TDD代碼,?并且也需要通過本次開發的測試用例代碼,?保證質量的繼承性。
效果
代碼如下:
<!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+'時'+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()); }/* 天控件 值選中后,改變時控件可選值 */ $("#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);/* 天值 最大和最小 都是一個值例如 {min:4294967294, max:4294967295}49710天6時28分15秒49710天6時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{}/* 更新分控件可選值,一旦選擇了最大值,這些控件范圍有可能是部分可選項,如果天選擇不為最大值,則這些控件需要包括全部可選項。*/$("#Hour").change();event.stopPropagation(); });/* 時控件 值選中后,改變分控件可選值 */ $("#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);/* 時值 最大和最小 都是一個值例如 {min:4294967294, max:4294967295}49710天6時28分15秒49710天6時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");}/* 更新秒控件可選值,一旦選擇了最大值,這些控件范圍有可能是部分可選項,如果天選擇不為最大值,則這些控件需要包括全部可選項。*/$("#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);/* 分值 最大和最小 都是一個值例如 {min:4294967294, max:4294967295}49710天6時28分15秒49710天6時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">時</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);/* 填充天控件可選項 */FillSelectOption("Day", minDay, maxDay);/* 觸發天控件change,初始化填充時分秒控件可選項 */$("#Day").change();/* 如果最大單位未達到,則隱藏掉對應控件 */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: 測試用例 Changes: *******************************************************************************/ /* 考慮使用jsunit整個控件考慮使用模塊化思想*/ 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!");} }/* 一般范圍測試: 1、頁面載入,沒有后臺賦值, 查看各個控件可選范圍:天 0-49710時 0-23分 0-59秒 0-59 2、MAX測試:a. 選擇天為 49710, 查看時選擇范圍為 0-6b. 選擇時為 6, 查看分選擇范圍為 0-28c. 選擇分為 28, 查看秒選擇范圍為 0-15, 選擇秒15 OKd. 再次切換分為 27, 查看秒 可選范圍 為 0-59e. 再次切換時為 5, 查看分 可選值為 0-59f. 再次切換天為 49709,查看時 可選值為 0-2349710天6時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測試范圍為 {min:4294967294, max:4294967295}49710天6時28分15秒49710天6時28分14秒查看各個控件可選值天 - 49710時 - 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分鐘測試范圍 {min:4294967235, max:4294967295}49710天6時28分15秒49710天6時27分15秒查看各個控件可選值天 - 49710時 - 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小時測試范圍 {min:4294963695, max:4294967295}49710天6時28分15秒49710天5時28分15秒查看各個控件可選值天 - 49710時 - 5-6分 - 28-59 選擇時為 5分 - 0-28 選擇時為 6秒 - 15-59 選擇分為 28,時為5秒 - 0-59 選擇分為 29,時為5秒 - 0-15 選擇分為 28, 時為6秒 - 0-59 選擇分為 27, 時為6*/ var range = {min:4294963695, max:4294967295} InitTimeScalar(range);TestSetGet(4294967295, true); TestSetGet(4294967296, false); TestSetGet(4294963695, true); TestSetGet(4294963694, false);/* range相差1天測試范圍 {min:4294880895, max:4294967295}49710天6時28分15秒49709天6時28分15秒查看各個控件可選值天 - 49709-49710時 - 6-23 選擇天為49709時 - 0-6 選擇天為49710選擇天為49709,時為7, 查看分秒范圍都為 0-59選擇天為49710,時為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天測試,查看最大和最小值如下可選1天0時0分0秒0天0時0分0秒*/ var range = {min:0, max:86400} InitTimeScalar(range);TestSetGet(86400, true); TestSetGet(86401, false); TestSetGet(0, true); TestSetGet(-1, false);/* range最大值不足1天測試天控件未顯示,時分秒最大最小值可選如下0天23時59分59秒0天0時0分0秒*/ var range = {min:0, max:86399} InitTimeScalar(range);TestSetGet(86399, true); TestSetGet(86400, false); TestSetGet(0, true); TestSetGet(-1, false);/* range最大值為1小時時分秒最大最小值可選如下0天1時0分0秒0天0時0分0秒*/ var range = {min:0, max:3600} InitTimeScalar(range);TestSetGet(3600, true); TestSetGet(3601, false); TestSetGet(0, true); TestSetGet(-1, false);/* range最大值為 3599時分秒最大最小值可選如下0天0時59分59秒0天0時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時1分0秒0天0時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時0分59秒0天0時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>?
在火狐上運行后,?控制臺上打印如下:
?
引申
TDD屬于單元測試范疇,?除了自己寫TDD測試函數,?也可以借助測試框架 XUnit
js有對應的 JSUnit
1、?JsUnit??官網 http://www.jsunit.net/
github上項目(若干年前, 已經不再維護,?替換品為 Jasmine)
https://github.com/pivotal/jsunit
使用方法介紹:
http://www.cnblogs.com/youcai/archive/2012/02/10/2345689.html
與其比較:??JsUnit適合較大測試對象,?測試結果比較直觀,??本控件規模小,?就不用此工具了。
此工具,?對于本文對象,?測試用例,?需要針對每種測試range,?單獨開一個html,?然后組成一個?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的測試框架:
http://qunitjs.com/
對于本文若干測試range,?可以容納與一個js文件中執行,?可以后續嘗試。
QUnit.test( "hello test", function( assert ) { assert.ok( 1 == "1", "Passed!" ); });?
轉載于:https://www.cnblogs.com/lightsong/p/4641893.html
總結
以上是生活随笔為你收集整理的JavasSript实现秒转换为“天时分秒”控件和TDD测试方法应用的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: HDU Senior's Gun (水
- 下一篇: 绝大部分项目都是跟金融创新、互联网、移动