*接上一次的第一部,当时实现了框架的大至思想和特性\程序集的动态载入等.这一节实现了基本的测试功能,现在放出来大家讨论. 上一节中我有提到过,BUG的跟踪可以用异常来实现,用纯c#做我也实在想不出还有其它的方法了,也就是自定义异常/系统异常抛出, 客户端来接收这个异常信息,有套机制来验证和跟踪记录BUG是否存在和存在数量/存在位置等等.. 下面是工具中捕捉异常记录bug的代码,通过反射程序集,动态调用测试用例方法.接收抛出的异常,如果有异常则记录bug点:
Code /// <summary> /// 测试方法 /// </summary> protected void TestingStart() { txtMainMessage.Text = string.Empty; //初初提示信息 if (asserblyName.Length <= 0) { MessageBox.Show("请载入要测试的程序集"); return; } bool isBug = false; //Bug状态记数器,默认为无BUG int isBugCount = 0; //Bug数据记数,默认为0 AlertsType isBugAlert = AlertsType.Red;//默认提示色为红色 Assembly assembly = Assembly.LoadFrom(asserblyName); //载入程序集 Type[] types = assembly.GetTypes(); //反射出所有类型 assionProgressBar1.Maximum = types.Length;//进度条最大值为类型数 assionProgressBar1.Value = 0;//当前进度为起始 0 assionProgressBar1.ProgressBarColor = Color.Green;//默认为绿色 //循环类型 foreach (var t in types) { TestClassAttribute testClass = IsCustomerAttribute.GetTestClassAttribute(t); //查询特性 //如果没有标记测试类,返回下一次循环 if (testClass == null) continue; //循环方法 foreach (var m in t.GetMethods()) { TestAttribute test = IsCustomerAttribute.GetTestAttribute(m); //查询特性 //如果没有标记测试方法,返回下一次循环 if (test == null) continue; //如果有黄色提示特性则显示为黄色 if (test.IsAlertType == AlertsType.Yellow) isBugAlert = AlertsType.Yellow; BindingFlags flags = BindingFlags.DeclaredOnly | BindingFlags.Public; object instance = null; //如果不是静态方法,则实例方法 if (!m.IsStatic) { instance = Instantiate(t); flags |= BindingFlags.Instance; } else { flags |= BindingFlags.Static; } //执行测试方法,并捕取异常信息 try { m.Invoke(instance, flags, null, null, null); } catch (Exception exp) { Exception bugException = exp.InnerException; //获取具体内部异常 //转换为Bug异常 try { BugException bexp = (BugException)bugException; //如果是显示抛出BUG异常信息,则记录Bug if (bexp.Message == "TestingBugReturn") { txtMainMessage.Text += "BUG:" + t.Name.ToString() + "-" + m.Name.ToString() + "\r\n\r\n"; //记录Bug位置 isBug = true; //有Bug isBugCount++; //Bug+1次 } } catch { txtMainMessage.Text += exp.InnerException.Message + "\r\n\r\n"; isBug = true; isBugCount++; continue; } } } assionProgressBar1.Value++;//循环一次步长加一步 Application.DoEvents(); } if (isBug == true) { if (isBugAlert == AlertsType.Red) assionProgressBar1.ProgressBarColor = Color.Red; //有Bug显示红色 else assionProgressBar1.ProgressBarColor = Color.Yellow; //有黄色提示特性显示黄色提示 lblBug.Text = "共有Bug" + isBugCount.ToString() + "个"; } else { assionProgressBar1.ProgressBarColor = Color.Green; //无Bug显示黄色 lblBug.Text = "共有Bug" + isBugCount.ToString() + "个"; } }
测试用例示例: Code /// <summary> /// 用于测试 BasicModule类 /// </summary> [TestClass] public class BasicModuleTest { /// <summary> /// 测试Add方法 /// </summary> [Test] public void Add() { BasicModule bm = new BasicModule(); int result = bm.Add(1, 2); Assert.AreEqual(result, 4); } /// <summary> /// 测试Add方法 /// </summary> [Test] public void Add2() { BasicModule bm = new BasicModule(); int result = bm.Add(1, 2); if (result != 5) Assert.BugBool(true); else Assert.BugBool(false); }}
开发过程中遇到了一个问题,WinForm自带的进度条控件不支持列改色彩,就是说是随着系统主题的(windowsxp以上系统),后来实在没有办法只 好自己实现一个简单的进度条自定义控件,虽然丑了一点,但终于可以变红色了哈哈.附带下控件的代码: Code partial class AssionProgressBar : UserControl { /// <summary> /// 必需的设计器变量。 /// </summary> private System.ComponentModel.IContainer components = null; /// <summary> /// 清理所有正在使用的资源。 /// </summary> /// <param name="disposing">如果应释放托管资源,为 true;否则为 false。</param> protected override void Dispose(bool disposing) { if (disposing && (components != null)) { components.Dispose(); } base.Dispose(disposing); } #region 组件设计器生成的代码 /// <summary> /// 设计器支持所需的方法 - 不要 /// 使用代码编辑器修改此方法的内容。 /// </summary> private void InitializeComponent() { this.SuspendLayout(); // // AssionProgressBar // this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 12F); this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; this.Name = "AssionProgressBar"; this.Size = new System.Drawing.Size(244, 30); this.ResumeLayout(false); } int min = 0; // 定义最小值变量,默认为0 int max = 100; // 定义最大值变量,默认为100 int val = 0; // 当前值,默认为0 Color BarColor = Color.Green; // 定义颜色,默认为绿色 protected override void OnResize(EventArgs e) { // Invalidate the control to get a repaint. this.Invalidate(); } /// <summary> /// 重写绘制方法 /// </summary> /// <param name="e"></param> protected override void OnPaint(PaintEventArgs e) { Graphics g = e.Graphics; SolidBrush brush = new SolidBrush(BarColor); float percent = (float)(val - min) / (float)(max - min); Rectangle rect = this.ClientRectangle; // Calculate area for drawing the progress. rect.Width = (int)((float)rect.Width * percent); // Draw the progress meter. g.FillRectangle(brush, rect); // Draw a three-dimensional border around the control. Draw3DBorder(g); // Clean up. brush.Dispose(); g.Dispose(); } /// <summary> /// 最小值 /// </summary> public int Minimum { get { return min; } set { // Prevent a negative value. if (value < 0) { min = 0; } // Make sure that the minimum value is never set higher than the maximum value. if (value > max) { min = value; min = value; } // Ensure value is still in range if (val < min) { val = min; } // Invalidate the control to get a repaint. this.Invalidate(); } } //最大值 public int Maximum { get { return max; } set { // Make sure that the maximum value is never set lower than the minimum value. if (value < min) { min = value; } max = value; // Make sure that value is still in range. if (val > max) { val = max; } // Invalidate the control to get a repaint. this.Invalidate(); } } /// <summary> /// 当前值 /// </summary> public int Value { get { return val; } set { int oldValue = val; // Make sure that the value does not stray outside the valid range. if (value < min) { val = min; } else if (value > max) { val = max; } else { val = value; } // Invalidate only the changed area. float percent; Rectangle newValueRect = this.ClientRectangle; Rectangle oldValueRect = this.ClientRectangle; // Use a new value to calculate the rectangle for progress. percent = (float)(val - min) / (float)(max - min); newValueRect.Width = (int)((float)newValueRect.Width * percent); // Use an old value to calculate the rectangle for progress. percent = (float)(oldValue - min) / (float)(max - min); oldValueRect.Width = (int)((float)oldValueRect.Width * percent); Rectangle updateRect = new Rectangle(); // Find only the part of the screen that must be updated. if (newValueRect.Width > oldValueRect.Width) { updateRect.X = oldValueRect.Size.Width; updateRect.Width = newValueRect.Width - oldValueRect.Width; } else { updateRect.X = newValueRect.Size.Width; updateRect.Width = oldValueRect.Width - newValueRect.Width; } updateRect.Height = this.Height; // Invalidate the intersection region only. this.Invalidate(updateRect); } } /// <summary> /// 进度条颜色 /// </summary> public Color ProgressBarColor { get { return BarColor; } set { BarColor = value; // Invalidate the control to get a repaint. this.Invalidate(); } } /// <summary> /// 绘制进度条 /// </summary> /// <param name="g"></param> private void Draw3DBorder(Graphics g) { int PenWidth = (int)Pens.White.Width; g.DrawLine(Pens.DarkGray, new Point(this.ClientRectangle.Left, this.ClientRectangle.Top), new Point(this.ClientRectangle.Width - PenWidth, this.ClientRectangle.Top)); g.DrawLine(Pens.DarkGray, new Point(this.ClientRectangle.Left, this.ClientRectangle.Top), new Point(this.ClientRectangle.Left, this.ClientRectangle.Height - PenWidth)); g.DrawLine(Pens.White, new Point(this.ClientRectangle.Left, this.ClientRectangle.Height - PenWidth), new Point(this.ClientRectangle.Width - PenWidth, this.ClientRectangle.Height - PenWidth)); g.DrawLine(Pens.White, new Point(this.ClientRectangle.Width - PenWidth, this.ClientRectangle.Top), new Point(this.ClientRectangle.Width - PenWidth, this.ClientRectangle.Height - PenWidth)); } #endregion }
老规距最后来一张运行效果图: 我写的不是代码,是轮子!