• 配合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[]数组存储制表符的思想,我还是照搬过来了,实践证明,这咱思想非常好,在此深表感谢!

    流浪是注定的宿命;
    漂泊是无尽的轮回。
  • 相关阅读:
    JavaScript获取键盘事件
    Java 虚拟机的内存结构
    Java 实现 Http 请求工具类
    HTML5之FileReader文件读取接口
    使用 PLSQL 连接 Oracle9i 数据库
    使用 Navicate 连接 Oracle9i 数据库
    Eclipse 刚检出的项目 Build path 的时候提示 No action available
    Eclipse 中 Debug 调试 java 代码一直报 Source not found
    mongodb 客户端工具
    spring 国际化
  • 原文地址:https://www.cnblogs.com/xpnew/p/1797370.html
Copyright © 2020-2023  润新知