配合NUnit時行單元測試的基類,可以在控制臺顯示表格

上一篇文章(在這里),總結了和NUnit單元測試工具,其中提到可以把測試類中把信息在控制臺輸出。不過在NUnit中,只是直接輸出文本,想要輸出復雜的內容,那就得自己實現了。

我的職業和任務主要就是Web 應用程序,里面有無數次是和數據庫打交道的,數據庫的話當然就少不了DataTable,如果能在測試的過程中,顯示出來DataTable里面的數據,當然再好不過了。

有了這個想法,那就行動吧。

 

圖一

 

 

這里面我封裝一個基類:class TestBase,它不加[TestFixture]指令,只是準備給其它使用NUnit進行單元測試的類做繼承。具體的功能就是封裝了兩個方法。

  1. SayTable(DataTable dt)   在控制臺顯示表格內的數據,“圖一”就是它運行起來的結果
  2. Say(string str)  包裝了 Console.WriteLine(str) ,這樣有了一個比較簡潔的方法名稱
  3. 這個類還有一個屬性:public int Length4CutStr   這個屬性是控制cell (單元格)內截取文字長度的。默認我設定為25

下面重點介紹一下SayTable這個方法。

這個方法的設計目標是:(一)可以顯示表格里面的數據;(二)可以包含字段(列)的名稱;(三)自動適應字段(列)內最長的那個cell;(四)使用制表符給表格內容加上邊框

前兩個目標比較容易實現,只要循環Columns或者Rows就可以完成了。

關鍵是后面這兩個,經過反復研究,也沒有找到最完美的辦法,也就是始終于法將內容對齊。最開始的時候以為,使用兩個空格就能補充一個漢字的位置,用肉眼觀察似乎是這樣,結果發現,不是那么回事, 最后截圖在再放大發現,在NUnit的控制臺界面上,英文是7個像素,而中文是13像素。按照中文英文1:2的方式,100個中文和200個英文或者數字,分兩行左端對齊,就能看到,英文那一行多出來14個字。換了一種算法,不簡單的按照個數,先計算出來空隙,然后再計算字符的數量,這個時候,又出現了小于7像素,不能用英文空格補齊的問題。不過總體來看,大體上還是對齊了,至少對于測試來說,不會讓人混淆表格里面的數據。雖然有點勉強,但是基本的目標也已經實現了。

 

下面給出類的代碼:

    /// <summary>
    /// 配合NUnit時行單元測試的基類
    /// 主要的作用是在控制臺輸出文本或者DataTable里面的內容
    /// 作者:xpnew.cnblogs.com http://blog.csdn.net/xpnew
    /// 發布日期:2010年8月11日
    /// 更新日期:2010年8月11日
    /// </summary>
    public class TestBase
    {

        public void Say(string str)
        {
            Console.WriteLine(str);
        }

        private int _Length4CutStr = 25;
        public int Length4CutStr { get { return _Length4CutStr; } set { _Length4CutStr = value; } }

        //private ArrayList _ColLength;
        private List<int> _ColLength = new List<int>();
        /// <summary>
        /// 在控制臺顯示DataTable的內容,可以自適應Cell的寬度,但是最多不能超過Length4CutStr屬性指定的值
        /// </summary>
        /// <param name="dt"></param>
        public void SayTable(DataTable dt)
        {
            TextCount tc = new TextCount();
            //獲得列的數量
            int col_count = dt.Columns.Count;
            string col_str;//單元格的內容;
            int field_length = 0;
            int field_length1 = 0;
            for (int i = 0; i < col_count; i++)
            {
                tc.str = dt.Columns[i].ColumnName;
                field_length =(tc.ChLength*13+tc.EnLength*7)/13;
                for (int j = 0; j < dt.Rows.Count; j++)
                {
                    col_str = dt.Rows[j][i].ToString();
                    if (dt.Columns[i].DataType == typeof(string) && col_str.Length > Length4CutStr)
                    {
                        col_str = col_str.Substring(0, Length4CutStr);
                        dt.Rows[j][i] = col_str;
                    }

                    tc.str = col_str;
                    field_length1 = (tc.ChLength * 13 + tc.EnLength * 7) / 13;
                    field_length = field_length > field_length1 ? field_length : field_length1;
                }
                field_length ++;
                _ColLength.Add(field_length);
            }
            char[] line_left = new char[3] { '┏', '┣', '┗' };
            char[] line_h = new char[3] { '━', '━', '━' };
            char[] line_mid2 = new char[3] { '┳', '╋', '┻' };
            char[] line_v = new char[3] { '┃', '┃', '┃' };
            char[] line_right = new char[3] { '┓', '┫', '┛' };

            StringBuilder sb = new StringBuilder();
            Say("顯示表格數據==========================");

            //行首:
            sb.Append(line_left[0]);
            for (int i = 0; i < col_count; i++)
            {
                if (i != 0)
                    sb.Append(line_mid2[0]);
                for(int j =0 ; j< _ColLength[i]; j++){
                    sb.Append(line_h[0]);
                }
            }
            sb.Append(line_right[0]);
            sb.Append('\n');

            for (int i = 0; i < col_count; i++)
            {
                sb.Append(line_v[0]);
                sb.Append(FillString(dt.Columns[i].ColumnName.Trim(), _ColLength[i]));
            }
            sb.Append(line_v[0]);
            sb.Append('\n');

            foreach (DataRow row in dt.Rows)
            {
                //行間:
                sb.Append(line_left[1]);
                for (int i = 0; i < col_count; i++)
                {
                    if (i != 0)
                        sb.Append(line_mid2[1]);
                    for (int j = 0; j < _ColLength[i]; j++)
                    {
                        sb.Append(line_h[1]);
                    }
                }
                sb.Append(line_right[1]);
                sb.Append('\n');
                
                sb.Append(line_v[0]);
                for (int i = 0; i < dt.Columns.Count; i++)
                {
                    sb.Append(FillString(row[i].ToString().Trim(), _ColLength[i]));
                    sb.Append(line_v[0]);
                }
                sb.Append("\n");


            }


            //行尾:
            sb.Append(line_left[2]);
            for (int i = 0; i < col_count; i++)
            {
                if (i != 0)
                    sb.Append(line_mid2[2]);
                for (int j = 0; j < _ColLength[i] ; j++)
                {
                    sb.Append(line_h[2]);
                }
            }
            sb.Append(line_right[2]);
            sb.Append('\n');


            Console.Write(sb.ToString());

        }

        private string FillString(string str, int len)
        {
            TextCount tc = new TextCount(str);
            int len1 = tc.ChLength * 13 + tc.EnLength * 7;
            int len2 = len*13 - len1;

            if (tc.EnLength > 0)
            {
                if (len2 > 7)
                {
                    //len2 = len2 / 7 + (len2 % 7 > 0 ? 1 : 0);
                    str = str + " ".PadRight(len2 / 7, ' ');
                }
                int len3 = len2 % 7;
                if (len3 > 4)
                {
                    str = str + " ";
                }
            }
            else
            {
                if (len2 > 13)
                {
                    //len2 = len2 / 7 + (len2 % 7 > 0 ? 1 : 0);
                    str = str + " ".PadRight(len2 / 13, ' ');
                }
                int len3 = len2 % 13;
                if (len3 > 7)
                {
                    str = str + " ";
                }
            }
            return str;
        }

    }

 

另外的一個類:  TextCount,可以分別統計中英文字符的個數(在當前應用中,這個是主要的作用),也可以統計中文英標點符號的個數。 

 

    /// <summary>
    /// 字符統計的功能
    /// </summary>
   public class TextCount
    {
        private StringBuilder sb;
        private string _str;
        public string str { get { return _str; } set { _str = value; Analyze(); } }
        public TextCount()
        {
           
        }
        public TextCount(string s)
        {
            _str = s;
            Analyze();
        }

        private int _len = 0;
        /// <summary>
        /// 粗略統計,等同于String.Length
        /// </summary>
        public int len { get { return _str.Length; } }
        private int _Len = 0;
        /// <summary>
        /// 精確長度,等同于AllLength
        /// </summary>
        public int Len { get { return _Len; } }
        private int _AllLength = 0;
        /// <summary>
        /// 全部長度
        /// </summary>
        public int AllLength { get { return _AllLength; } }
        private int _ChLength = 0;
        /// <summary>
        /// 中文字數
        /// </summary>
        public int ChLength { get { return _ChLength; } }
        private int _EnLength = 0;
        /// <summary>
        /// 英文字數
        /// </summary>
        public int EnLength { get { return _EnLength; } }


        private int _LetterLength = 0;
        /// <summary>
        /// 純字母字數
        /// </summary>
        public int LetterLength { get { return _LetterLength; } }

        /// <summary>
        /// 英文符號數量
        /// </summary>
        private int _SymbolLength = 0;
        public int SymbolLength { get { return _SymbolLength; } }

        private int _ChSymbolLength = 0;
        /// <summary>
        /// 中文符號字數
        /// </summary>
        /// <remarks>這個只能獲取預定義中文符號列表</remarks>
        public int ChSymbolLength { get { return _ChSymbolLength; } }


        private string _ChSymbilDefine = ",。;“”:?、!《》·「」『』〖〗【】※¥";

        /// <summary>
        /// 解析字符串,完成統計,每次發第生改變都需要調用
        /// </summary>
        private void Analyze()
        {
            _EnLength = _ChLength = _AllLength = _Len = _LetterLength = _SymbolLength = _ChSymbolLength = 0;

            for (int i = 0; i <_str.Length; i++)
            {
                //計算文本長度,區分中英文字符,中文算兩個長度,英文算一個長度
                byte[] byte_len = Encoding.Default.GetBytes(_str.Substring(i, 1));
                if (byte_len.Length > 1)
                {
                    _ChLength++;//如果長度大于1,是中文,占兩個字節,+2

                    if (_ChSymbilDefine.IndexOf(_str.Substring(i, 1)) >-1)
                    {
                        _ChSymbolLength++;
                    }

                }
                else
                {
                    _EnLength++;//如果長度等于1,是英文,占一個字節,+1


                    /********************************
                     * 其實可以連數字、空格都給統計出來,但是實際中用處不多
                     * 
                    if (Char.IsLetter(_str[i]))
                    {
                        //_LetterLength++;
                    }else if(Char.IsNumber(_str[i]))
                    {

                    }

                     * 
                     ************************************** */
                    if (Char.IsLetterOrDigit(_str[i]))
                        _LetterLength++;

                }
            }

            _AllLength = _Len = _EnLength + _ChLength*2;
            _SymbolLength = _EnLength - _LetterLength;
        }

    }

 

另外,本文參考了《控制臺打印表格》 這篇文章是C++的代碼,我看不太懂,不過里面使用char[]數組存儲制表符的思想,我還是照搬過來了,實踐證明,這咱思想非常好,在此深表感謝!

posted @ 2010-08-11 15:40  柳城之城  閱讀(...)  評論(...編輯  收藏
三d开奖结果走势图