我已经阅读过关于单元测试的内容,并且听到了其他人宣传其实用性的许多喧嚣,并希望看到它的实际应用.因此,我从我创建的一个简单应用程序中选择了这个基本类.我不知道测试会如何帮助我,我希望你们中的一个能够通过指出可以测试这些代码的哪些部分以及这些测试的外观来帮助我看到它的好处.那么,我将如何编写以下代码的单元测试?
public class Hole : INotifyPropertyChanged { #region Field Definitions private double _AbsX; private double _AbsY; private double _CanvasX { get; set; } private double _CanvasY { get; set; } private bool _Visible; private double _HoleDia = 20; private HoleTypes _HoleType; private int _HoleNumber; private double _StrokeThickness = 1; private Brush _StrokeColor = new SolidColorBrush(Colors.Black); private HolePattern _ParentPattern; #endregion public enum HoleTypes { Drilled, Tapped, CounterBored, CounterSunk }; public Ellipse HoleEntity = new Ellipse(); public Ellipse HoleDecorator = new Ellipse(); public TextBlock HoleLabel = new TextBlock(); private static DoubleCollection HiddenLinePattern = new DoubleCollection(new double[] { 5, 5 }); public int HoleNumber { get { return _HoleNumber; } set { _HoleNumber = value; HoleLabel.Text = value.ToString(); NotifyPropertyChanged("HoleNumber"); } } public double HoleLabelX { get; set; } public double HoleLabelY { get; set; } public string AbsXDisplay { get; set; } public string AbsYDisplay { get; set; } public event PropertyChangedEventHandler PropertyChanged; //public event MouseEventHandler MouseActivity; // Constructor public Hole() { //_HoleDia = 20.0; _Visible = true; //this.ParentPattern = WhoIsTheParent; HoleEntity.Tag = this; HoleEntity.Width = _HoleDia; HoleEntity.Height = _HoleDia; HoleDecorator.Tag = this; HoleDecorator.Width = 0; HoleDecorator.Height = 0; //HoleLabel.Text = x.ToString(); HoleLabel.TextAlignment = TextAlignment.Center; HoleLabel.Foreground = new SolidColorBrush(Colors.White); HoleLabel.FontSize = 12; this.StrokeThickness = _StrokeThickness; this.StrokeColor = _StrokeColor; //HoleEntity.Stroke = Brushes.Black; //HoleDecorator.Stroke = HoleEntity.Stroke; //HoleDecorator.StrokeThickness = HoleEntity.StrokeThickness; //HiddenLinePattern=DoubleCollection(new double[]{5, 5}); } public void NotifyPropertyChanged(String info) { if (PropertyChanged != null) { PropertyChanged(this, new PropertyChangedEventArgs(info)); } } #region Properties public HolePattern ParentPattern { get { return _ParentPattern; } set { _ParentPattern = value; } } public bool Visible { get { return _Visible; } set { _Visible = value; HoleEntity.Visibility = value ? Visibility.Visible : Visibility.Collapsed; HoleDecorator.Visibility = HoleEntity.Visibility; SetCoordDisplayValues(); NotifyPropertyChanged("Visible"); } } public double AbsX { get { return _AbsX; } set { _AbsX = value; SetCoordDisplayValues(); NotifyPropertyChanged("AbsX"); } } public double AbsY { get { return _AbsY; } set { _AbsY = value; SetCoordDisplayValues(); NotifyPropertyChanged("AbsY"); } } private void SetCoordDisplayValues() { AbsXDisplay = HoleEntity.Visibility == Visibility.Visible ? String.Format("{0:f4}", _AbsX) : ""; AbsYDisplay = HoleEntity.Visibility == Visibility.Visible ? String.Format("{0:f4}", _AbsY) : ""; NotifyPropertyChanged("AbsXDisplay"); NotifyPropertyChanged("AbsYDisplay"); } public double CanvasX { get { return _CanvasX; } set { if (value == _CanvasX) { return; } _CanvasX = value; UpdateEntities(); NotifyPropertyChanged("CanvasX"); } } public double CanvasY { get { return _CanvasY; } set { if (value == _CanvasY) { return; } _CanvasY = value; UpdateEntities(); NotifyPropertyChanged("CanvasY"); } } public HoleTypes HoleType { get { return _HoleType; } set { if (value != _HoleType) { _HoleType = value; UpdateHoleType(); NotifyPropertyChanged("HoleType"); } } } public double HoleDia { get { return _HoleDia; } set { if (value != _HoleDia) { _HoleDia = value; HoleEntity.Width = value; HoleEntity.Height = value; UpdateHoleType(); NotifyPropertyChanged("HoleDia"); } } } public double StrokeThickness { get { return _StrokeThickness; } //Setting this StrokeThickness will also set Decorator set { _StrokeThickness = value; this.HoleEntity.StrokeThickness = value; this.HoleDecorator.StrokeThickness = value; NotifyPropertyChanged("StrokeThickness"); } } public Brush StrokeColor { get { return _StrokeColor; } //Setting this StrokeThickness will also set Decorator set { _StrokeColor = value; this.HoleEntity.Stroke = value; this.HoleDecorator.Stroke = value; NotifyPropertyChanged("StrokeColor"); } } #endregion #region Methods private void UpdateEntities() { //-- Update Margins for graph positioning HoleEntity.Margin = new Thickness (CanvasX - HoleDia / 2, CanvasY - HoleDia / 2, 0, 0); HoleDecorator.Margin = new Thickness (CanvasX - HoleDecorator.Width / 2, CanvasY - HoleDecorator.Width / 2, 0, 0); HoleLabel.Margin = new Thickness ((CanvasX * 1.0) - HoleLabel.FontSize * .3, (CanvasY * 1.0) - HoleLabel.FontSize * .6, 0, 0); } private void UpdateHoleType() { switch (this.HoleType) { case HoleTypes.Drilled: //Drilled only HoleDecorator.Visibility = Visibility.Collapsed; break; case HoleTypes.Tapped: // Drilled & Tapped HoleDecorator.Visibility = (this.Visible == true) ? Visibility.Visible : Visibility.Collapsed; HoleDecorator.Width = HoleEntity.Width * 1.2; HoleDecorator.Height = HoleDecorator.Width; HoleDecorator.StrokeDashArray = LinePatterns.HiddenLinePattern(1); break; case HoleTypes.CounterBored: // Drilled & CounterBored HoleDecorator.Visibility = (this.Visible == true) ? Visibility.Visible : Visibility.Collapsed; HoleDecorator.Width = HoleEntity.Width * 1.5; HoleDecorator.Height = HoleDecorator.Width; HoleDecorator.StrokeDashArray = null; break; case HoleTypes.CounterSunk: // Drilled & CounterSunk HoleDecorator.Visibility = (this.Visible == true) ? Visibility.Visible : Visibility.Collapsed; HoleDecorator.Width = HoleEntity.Width * 1.8; HoleDecorator.Height = HoleDecorator.Width; HoleDecorator.StrokeDashArray = null; break; } UpdateEntities(); } #endregion }
Gord.. 6
单元测试示例:
验证是否使用正确的事件args触发了PropertyChanged事件.在测试中使用反射来迭代设置值的所有属性并检查事件.
通常这是通过测试框架(如NUnit)完成的.
(有趣的是,您会注意到ParentPattern属性不会触发事件.)
单元测试示例:
验证是否使用正确的事件args触发了PropertyChanged事件.在测试中使用反射来迭代设置值的所有属性并检查事件.
通常这是通过测试框架(如NUnit)完成的.
(有趣的是,您会注意到ParentPattern属性不会触发事件.)