PageRenderTime 14ms CodeModel.GetById 1ms app.highlight 10ms RepoModel.GetById 1ms app.codeStats 0ms

/src/NUnit/interfaces/Extensibility/ParameterSet.cs

#
C# | 324 lines | 198 code | 35 blank | 91 comment | 25 complexity | c64c3dd023361262f4b1cfd29d39e70b MD5 | raw file
  1// ****************************************************************
  2// Copyright 2008, Charlie Poole
  3// This is free software licensed under the NUnit license. You may
  4// obtain a copy of the license at http://nunit.org
  5// ****************************************************************
  6
  7using System;
  8using System.Collections;
  9using System.Collections.Specialized;
 10using System.Reflection;
 11
 12namespace NUnit.Core.Extensibility
 13{
 14    /// <summary>
 15    /// ParameterSet encapsulates method arguments and
 16    /// other selected parameters needed for constructing
 17    /// a parameterized test case.
 18    /// </summary>
 19    public class ParameterSet : NUnit.Framework.ITestCaseData
 20    {
 21        #region Constants
 22        private static readonly string DESCRIPTION = "_DESCRIPTION";
 23        private static readonly string IGNOREREASON = "_IGNOREREASON";
 24        private static readonly string CATEGORIES = "_CATEGORIES";
 25        #endregion
 26
 27        #region Instance Fields
 28        private RunState runState;
 29        private Exception providerException;
 30        private object[] arguments;
 31        private object[] originalArguments;
 32        private System.Type expectedExceptionType;
 33        private string expectedExceptionName;
 34        private string expectedMessage;
 35        private string matchType;
 36        private object result;
 37        private string testName;
 38        private string ignoreReason;
 39        private bool isIgnored;
 40        private bool hasExpectedResult;
 41
 42        /// <summary>
 43        /// A dictionary of properties, used to add information
 44        /// to tests without requiring the class to change.
 45        /// </summary>
 46        private IDictionary properties;
 47        #endregion
 48
 49        #region Properties
 50        /// <summary>
 51        /// The RunState for this set of parameters.
 52        /// </summary>
 53        public RunState RunState
 54        {
 55            get { return runState; }
 56            set { runState = value; }
 57        }
 58
 59        /// <summary>
 60        /// The reason for not running the test case
 61        /// represented by this ParameterSet
 62        /// </summary>
 63        public string NotRunReason
 64        {
 65            get { return (string) Properties[IGNOREREASON]; }
 66        }
 67
 68        /// <summary>
 69        /// Holds any exception thrown by the parameter provider
 70        /// </summary>
 71        public Exception ProviderException
 72        {
 73            get { return providerException; }
 74        }
 75
 76        /// <summary>
 77        /// The arguments to be used in running the test,
 78        /// which must match the method signature.
 79        /// </summary>
 80        public object[] Arguments
 81        {
 82            get { return arguments; }
 83            set 
 84            {
 85                arguments = value;
 86
 87                if (originalArguments == null)
 88                    originalArguments = value;
 89            }
 90        }
 91
 92        /// <summary>
 93        /// The original arguments supplied by the user,
 94        /// used for display purposes.
 95        /// </summary>
 96        public object[] OriginalArguments
 97        {
 98            get { return originalArguments; }
 99        }
100
101        /// <summary>
102        /// The Type of any exception that is expected.
103        /// </summary>
104        public System.Type ExpectedException
105        {
106            get { return expectedExceptionType; }
107            set { expectedExceptionType = value; }
108        }
109
110        /// <summary>
111        /// The FullName of any exception that is expected
112        /// </summary>
113        public string ExpectedExceptionName
114        {
115            get { return expectedExceptionName; }
116            set { expectedExceptionName = value; }
117        }
118
119        /// <summary>
120        /// The Message of any exception that is expected
121        /// </summary>
122        public string ExpectedMessage
123        {
124        	get { return expectedMessage; }
125        	set { expectedMessage = value; }
126        }
127
128        /// <summary>
129        ///  Gets or sets the type of match to be performed on the expected message
130        /// </summary>
131        public string MatchType
132        {
133            get { return matchType; }
134            set { matchType = value; }
135        }
136
137        /// <summary>
138        /// The expected result of the test, which
139        /// must match the method return type.
140        /// </summary>
141        public object Result
142        {
143            get { return result; }
144            set 
145            { 
146                result = value;
147                hasExpectedResult = true;
148            }
149        }
150
151        /// <summary>
152        /// Returns true if an expected result has been 
153        /// specified for this parameter set.
154        /// </summary>
155        public bool HasExpectedResult
156        {
157            get { return hasExpectedResult; }
158        }
159
160        /// <summary>
161        /// A description to be applied to this test case
162        /// </summary>
163        public string Description
164        {
165            get { return (string) Properties[DESCRIPTION]; }
166            set 
167            {
168                if (value != null)
169                    Properties[DESCRIPTION] = value;
170                else
171                    Properties.Remove(DESCRIPTION);
172            }
173        }
174
175        /// <summary>
176        /// A name to be used for this test case in lieu
177        /// of the standard generated name containing
178        /// the argument list.
179        /// </summary>
180        public string TestName
181        {
182            get { return testName; }
183            set { testName = value; }
184        }
185
186        /// <summary>
187        /// Gets or sets a value indicating whether this <see cref="ParameterSet"/> is ignored.
188        /// </summary>
189        /// <value><c>true</c> if ignored; otherwise, <c>false</c>.</value>
190        public bool Ignored
191        {
192            get { return isIgnored; }
193            set { isIgnored = value; }
194        }
195
196        /// <summary>
197        /// Gets or sets the ignore reason.
198        /// </summary>
199        /// <value>The ignore reason.</value>
200        public string IgnoreReason
201        {
202            get { return ignoreReason; }
203            set { ignoreReason = value; }
204        }
205
206        /// <summary>
207        /// Gets a list of categories associated with this test.
208        /// </summary>
209        public IList Categories
210        {
211            get
212            {
213                if (Properties[CATEGORIES] == null)
214                    Properties[CATEGORIES] = new ArrayList();
215
216                return (IList)Properties[CATEGORIES];
217            }
218        }
219
220        /// <summary>
221        /// Gets the property dictionary for this test
222        /// </summary>
223        public IDictionary Properties
224        {
225            get
226            {
227                if (properties == null)
228                    properties = new ListDictionary();
229
230                return properties;
231            }
232        }
233        #endregion
234
235        #region Constructors
236        /// <summary>
237        /// Construct a non-runnable ParameterSet, specifying
238        /// the provider excetpion that made it invalid.
239        /// </summary>
240        public ParameterSet(Exception exception)
241        {
242            this.runState = RunState.NotRunnable;
243            this.providerException = exception;
244        }
245
246        /// <summary>
247        /// Construct an empty parameter set, which
248        /// defaults to being Runnable.
249        /// </summary>
250        public ParameterSet()
251        {
252            this.runState = RunState.Runnable;
253        }
254        #endregion
255
256        #region Static Methods
257        /// <summary>
258        /// Constructs a ParameterSet from another object, accessing properties 
259        /// by reflection. The object must expose at least an Arguments property
260        /// in order for the test to be runnable.
261        /// </summary>
262        /// <param name="source"></param>
263        public static ParameterSet FromDataSource(object source)
264        {
265            ParameterSet parms = new ParameterSet();
266
267            parms.Arguments = GetParm(source, PropertyNames.Arguments) as object[];
268            parms.ExpectedException = GetParm(source, PropertyNames.ExpectedException) as Type;
269            if (parms.ExpectedException != null)
270                parms.ExpectedExceptionName = parms.ExpectedException.FullName;
271            else
272                parms.ExpectedExceptionName = GetParm(source, PropertyNames.ExpectedExceptionName) as string;
273            parms.ExpectedMessage = GetParm(source, PropertyNames.ExpectedMessage) as string;
274            object matchEnum = GetParm(source, PropertyNames.MatchType);
275            if ( matchEnum != null )
276                parms.MatchType = matchEnum.ToString();
277            parms.Result = GetParm(source, PropertyNames.Result);
278            parms.Description = GetParm(source, PropertyNames.Description) as string;
279            parms.TestName = GetParm(source, PropertyNames.TestName) as string;
280
281            object objIgnore = GetParm(source, PropertyNames.Ignored);
282            if ( objIgnore != null )
283                parms.Ignored = (bool)objIgnore;
284            parms.IgnoreReason = GetParm(source, PropertyNames.IgnoreReason) as string;
285
286            // Some sources may also implement Properties and/or Categories
287            bool gotCategories = false;
288            IDictionary props = GetParm(source, PropertyNames.Properties) as IDictionary;
289            if ( props != null )
290                foreach (string key in props.Keys)
291                {
292                    parms.Properties.Add(key, props[key]);
293                    if (key == CATEGORIES) gotCategories = true;
294                }
295
296            // Some sources implement Categories. They may have been
297            // provided as properties or they may be separate.
298            if (!gotCategories)
299            {
300                IList categories = GetParm(source, PropertyNames.Categories) as IList;
301                if (categories != null) 
302                    foreach (string cat in categories)
303                        parms.Categories.Add(cat);
304            }
305
306            return parms;
307        }
308
309        private static object GetParm(object source, string name)
310        {
311            Type type = source.GetType();
312            PropertyInfo prop = type.GetProperty(name, BindingFlags.Instance | BindingFlags.Public | BindingFlags.GetProperty);
313            if (prop != null)
314                return prop.GetValue(source, null);
315
316            FieldInfo field = type.GetField(name, BindingFlags.Instance | BindingFlags.Public | BindingFlags.GetField);
317            if (field != null)
318                return field.GetValue(source);
319
320            return null;
321        }
322        #endregion
323    }
324}