Welcome to mirror list, hosted at ThFree Co, Russian Federation.

mono-contribution-howto « web - github.com/mono/mono.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
blob: ea3a4eaae53af0e0c3c77c7daf87bcf461f17a17 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551

			<Mono newbie coders start file>
	<h1> A little help for mono newbie coders </h1>


	For those who are new to Mono and are impatient to contribute
	with code (uhh... you are brave!!) here is the document you 
	should read.

	
	You will see all Mono hackers say the same (great minds have
	similar way of thinking): First, DO WRITE TESTS!!!. In order
	to do that:
	
	<ul>
		* Start with the NUnit Tests Guidelines.  In the cvs
	    	  they are located at: mcs/class/doc/NUnitGuideli...

		* But wait, this is a document for impatient
	    	  people. So EVERYTHING should be here. Well, it is. 
	</ul>


	<h2> The NUnit Tests Guidelines document </h2>

	Mono NUnit Test Guidelines and Best Practices

	Authors: Nick Drochak  <ndrochak@gol.com>
	Martin Baulig  <martin@gnome.org>
	Last Update: 2002-03-02
	Rev: 0.3

 <b> Purpose </b>

	This document captures all the good ideas people have had 
	about writing NUnit tests for the mono project. This document 
	will be useful for anyone who writes or maintains unit tests.

 <b> Other resources </b>

	- mcs/class/README has an explanation of the build process and
	  how it relates to the tests.
	- http://nunit.sourceforge.net is the place to find out about 
	  NUnit

 <b> Getting Started </b>

	If you are new to writing NUnit tests, there is a template 
	you may use to help get started. The file is:

	mcs/class/doc/TemplateTest.cs


	(2.- This is the point two!. This file is just after the end 
	of the guidelines. Copy/paste it in another buffer. And keep 
	reading.)

	Save a copy of this file in the appropriate test subdirecty 
	(see below), and replace all the [text] markers with 
	appropriate code. Comments in the template are there to guide 
	you. You should also look at existing tests to see how other 
	people have written them. 

	mcs/class/corlib/Test/System.Collections/CollectionBaseTest.cs 

	is a small one that might help.

	(3.- You reached the third point. And as expected, it's just 
	here to tell you that the content of CollectionBaseTest.cs is 
	after the TemplateTest.cs code at the end of these 
	guidelines.)

	The directory that will contain your new file depends on the
	assembly/namespace of the class for which you are creating the
	tests. Under mcs/class there is a directory for each assembly. 
	In each assembly there is a Test directory, e.g. 
	mcs/class/corlib/Test. In the Test directory there are 
	sub-directories for each namespace in the assembly, e.g. 
	mcs/class/corlib/Test/Sytem. Put your new test file in the 
	appropriate sub-directory under Test for the class you are
	testing.

	Once your test class is complete, you need to add it to the
	AllTests.cs file in the same directory as your new test. Add a 
	call to "suite.AddTest()" passing the name of your new test 
	class's suite property as the parameter.  You will see examples 
	in the AllTests.cs file, so just copy and paste inside there.

	Once all of that is done, you can do a 'make test' from the top 
	mcs directory.  Your test class will be automagically included 
	in the build and the tests will be run along with all the 
	others.

 <b> Tips </b>

 <b> Provide an unique error message for Assert() </b>

	Include an unique message for each Assert() so that when the 
	assert fails, it is trivial to locate the failing one. 
	Otherwise, it may be difficult to determine which part of the 
	test is failing. A good way to ensure unique messages is to use 
	something like #A01, #A02 etc.

    	Bad:
<pre>
	AssertEquals("array match", compare[0], i1[0]);
	AssertEquals("array match", compare[1], i1[1]);
	AssertEquals("array match", compare[2], i1[2]);
	AssertEquals("array match", compare[3], i1[3]);
</pre>
    	Good:
<pre>
	AssertEquals("#A01", compare[0], i1[0]);
	AssertEquals("#A02", compare[1], i1[1]);
	AssertEquals("#A03", compare[2], i1[2]);
	AssertEquals("#A04", compare[3], i1[3]);
</pre>
	Once you used such a number in an Assert(), don't change it 
	later on - people might use it it identify the test in bug 
	reports or in mailing lists.

 <b> Use AssertEquals() to compare things, not Assert(). </b>

	Never compare two values with Assert() - if the test fails, 
	people have no idea what went wrong while AssertEquals() 
	reports the failed value.

    	Bad:
<pre>
        Assert ("A01", myTicks[0] == t1.Ticks);
</pre>
    	Good:
<pre>
        AssertEquals ("A01", myTicks[0], t1.Ticks);
</pre>

 <b> Constructors </b>

	When writing your testcase, please make sure to provide a 
	constructor which takes no arguments:

<pre>
        public class DateTimeTest : TestCase
        {

                public DateTimeTest() : base ("[MonoTests.System.DateTimeTest]") {}
                public DateTimeTest (string name): base(name) {}

        	public static ITest Suite
                {
                        get {
                                TestSuite suite = new TestSuite ();
        			return suite;
        		}
        	}
        }
</pre>

 <b> Namespace </b>

	Please keep the namespace within each test directory
	consistent - all tests which are referenced in the same
	AllTests.cs must be in the same namespace. Of course you can
	use subnamespaces as you like - especially for subdirectories
	of your testsuite.
	
	For instance, if your AllTests.cs is in namespace "MonoTests"
	and you have a subdirectory called "System", you can put all
	the tests in that dir into namespace "MonoTests.System".

 <b> Test your test with the microsoft runtime </b>

	If possible, try to run your testsuite with the Microsoft
	runtime on Windows and make sure all tests in it pass. This is
	especially important if you're writing a totally new testcase
	- without this check you can never be sure that your testcase
	contains no bugs ....
	
	Don't worry if you're writing your test on Linux, other people
	can test it for you on Windows.
	
	Sometimes you may discover that a test doesn't show the
	expected result when run with the Microsoft runtime - either
	because there is a bug in their runtime or something is
	misleading or wrong in their documentation. In this case,
	please put a detailed description of the problem to
	mcs/class/doc/API-notes and do also report it to the list -
	we'll forward this to the Microsoft people from time to time
	to help them fix their documentation and runtime.

<pre>
-------------------- TemplateTest.cs begins ----------

	// this is a template for making NUnit tests.  Text enclosed 
	// in square brackets (and the brackets themselves) should be 
	// replaced by appropiate code.

	// [File Name].cs - NUnit Test Cases for [explain here]
	//
	// [Author Name] ([Author email Address])
	//
	// (C) [Copyright holder]
	// 

	// these are the standard namespaces you will need.  You may 
	// need to add more depending on your tests.
	using NUnit.Framework;
	using System;

	// all test namespaces start with "MonoTests."  Append the 
	// Namespace that contains the class you are testing, e.g. 
	// MonoTests.System.Collections
	namespace MonoTests.[Namespace]
	{

	// the class name should end with "Test" and start with the name 
	// of the class you are testing, e.g. CollectionBaseTest
	public class [Class to be tested]Test : TestCase {
	
	// there should be two constructors for your class.  The first 
	// one (without parameters) should set the name to something 
	// unique.
	// Of course the name of the method is the same as the name of 
	// the class
	public [Constructor]() : base ("[Namespace.Class]") {}
	public [Constructor](string name) : base(name) {}

	// this method is run before each Test* method is called. You 
	// can put variable initialization, etc. here that is common to 
	// each test.
	// Just leave the method empty if you don't need to use it.
	protected override void SetUp() {}

	// this method is run after each Test* method is called. You 
	// can put clean-up code, etc. here.  Whatever needs to be done 
	// after each test. Just leave the method empty if you don't need 
	// to use it.
	protected override void TearDown() {}

	// this property is required.  You need change the parameter for
	// typeof() below to be your class.
	public static ITest Suite {
		get { 
			return new TestSuite(typeof([Classname here])); 
		}
	}

	// this is just one of probably many test methods in your test 
	// class. each test method must start with "Test".  All methods 
	// in your class which start with "Test" will be automagically 
	// called by the NUnit framework.
	public void Test[Something] {
		// inside here you will exercise your class and then 
		// call Assert()
	}
}

---------------------- TemplateTest.cs ends --------------

---------------------- CollectionBaseTest.cs begins ------
	//
	// System.Collections.CollectionBase
	// Test suite for System.Collections.CollectionBase
	//
	// Author:
	//    Nick D. Drochak II
	//
	// (C) 2001 Nick D. Drochak II
	//


	using System;
	using System.Collections;
	using NUnit.Framework;

	namespace MonoTests.System.Collections
	{

	public class CollectionBaseTest : TestCase 	
	{
		public CollectionBaseTest () : base 
			("System.Collection.CollectionBase testsuite") 
			{}
		public CollectionBaseTest (String name) : base (name) 
			{}

		// We need a concrete class to test the abstract base 
		// class
		public class ConcreteCollection : CollectionBase 
		{
			// These fields are used as markers to test 
			// the On* hooks.
			public bool onClearFired;
			public bool onClearCompleteFired;

			public bool onInsertFired;
			public int onInsertIndex;
			public bool onInsertCompleteFired;
			public int onInsertCompleteIndex;

			public bool onRemoveFired;
			public int onRemoveIndex;
			public bool onRemoveCompleteFired;
			public int onRemoveCompleteIndex;

			public bool onSetFired;
			public int onSetOldValue;
			public int onSetNewValue;
			public bool onSetCompleteFired;
			public int onSetCompleteOldValue;
			public int onSetCompleteNewValue;

			// This constructor is used to test OnValid()
			public ConcreteCollection()	
			{
				IList listObj;
				listObj = this;
				listObj.Add(null);
			}

			// This constructor puts consecutive integers into the list
			public ConcreteCollection(int i) {
				IList listObj;
				listObj = this;

				int j;
				for (j = 0; j< i; j++) {
					listObj.Add(j);
				}
			}

			// A helper method to look at a value in the 
			// list at a specific index
			public int PeekAt(int index)
			{
				IList listObj;
				listObj = this;
				return (int) listObj[index];
			}

			// Mark the flag if this hook is fired
			protected override void OnClear() {
				this.onClearFired = true;
			}

			// Mark the flag if this hook is fired
			protected override void OnClearComplete() 
			{
				this.onClearCompleteFired = true;
			}

			// Mark the flag, and save the paramter if 
			// this hook is fired
			protected override void OnInsert(int index, 
							object value) 
			{
				this.onInsertFired = true;
				this.onInsertIndex = index;
			}

			// Mark the flag, and save the paramter if 
			// this hook is fired
			protected override void OnInsertComplete(int index, 
							object value) 
			{
				this.onInsertCompleteFired = true;
				this.onInsertCompleteIndex = index;
			}
		
			// Mark the flag, and save the paramter if this hook 
			// is fired
			protected override void OnRemove(int index, 
							object value) 
			{
				this.onRemoveFired = true;
				this.onRemoveIndex = index;
			}
		
			// Mark the flag, and save the paramter if this hook 
			// is fired
			protected override void OnRemoveComplete(int index, 
								object value) 
			{
				this.onRemoveCompleteFired = true;
				this.onRemoveCompleteIndex = index;
			}
		
			// Mark the flag, and save the paramters if this hook 
			// is fired
			protected override void OnSet(int index, object oldValue, 
								object newValue) 
			{
				this.onSetFired = true;
				this.onSetOldValue = (int) oldValue;
				this.onSetNewValue = (int) newValue;
			}
		
			// Mark the flag, and save the paramters if this hook 
			// is fired
			protected override void OnSetComplete(int index, 
							object oldValue, 
							object newValue) 
			{
				this.onSetCompleteFired = true;
				this.onSetCompleteOldValue = (int) oldValue;
				this.onSetCompleteNewValue = (int) newValue;
			}
		}  // public class ConcreteCollection

		public static ITest Suite {
			get {
				return new TestSuite 
					(typeof(CollectionBaseTest));
			}
		}

		// Check the count property
		public void TestCount() {
			ConcreteCollection myCollection;
			myCollection = new ConcreteCollection(4);
			Assert(4 == myCollection.Count);
		}

	// Make sure GetEnumerator returns an object
	public void TestGetEnumerator() {
		ConcreteCollection myCollection;
		myCollection = new ConcreteCollection(4);
		Assert(null != myCollection.GetEnumerator());
	}

	// OnValid disallows nulls
	public void TestOnValid() {
		ConcreteCollection myCollection;
		try {
			myCollection = new ConcreteCollection();
		}
		catch (ArgumentNullException) {
		}
	}

	// Test various Insert paths
	public void TestInsert() {
		ConcreteCollection myCollection;
		int numberOfItems;
		numberOfItems = 3;
		// The constructor inserts
		myCollection = new ConcreteCollection(numberOfItems);
		Assert(myCollection.onInsertFired);
		Assert(myCollection.onInsertCompleteFired);

		// Using the IList interface, check inserts in the middle
		IList listObj = myCollection;
		listObj.Insert(1, 9);
		Assert(myCollection.onInsertIndex == 1);
		Assert(myCollection.onInsertCompleteIndex == 1);
		Assert(myCollection.PeekAt(1) == 9);
	}

	// Test Clear and it's hooks
	public void TestClear() 
	{
		ConcreteCollection myCollection;
		int numberOfItems;
		numberOfItems = 1;
		myCollection = new ConcreteCollection(numberOfItems);
		myCollection.Clear();
		Assert(myCollection.Count == 0);
		Assert(myCollection.onClearFired);
		Assert(myCollection.onClearCompleteFired);
	}

	// Test RemoveAt, other removes and the hooks
	public void TestRemove() 
	{
		ConcreteCollection myCollection;
		int numberOfItems;
		numberOfItems = 3;
		// Set up a test collection
		myCollection = new ConcreteCollection(numberOfItems);

		// The list is 0-based.  So if we remove the second one
		myCollection.RemoveAt(1);

		// We should see the original third one in it's place
		Assert(myCollection.PeekAt(1) == 2);
		Assert(myCollection.onRemoveFired);
		Assert(myCollection.onRemoveIndex == 1);
		Assert(myCollection.onRemoveCompleteFired);
		Assert(myCollection.onRemoveCompleteIndex == 1);
		IList listObj = myCollection;
		listObj.Remove(0);
		// Confirm parameters are being passed to the hooks
		Assert(myCollection.onRemoveIndex == 0);
		Assert(myCollection.onRemoveCompleteIndex == 0);
	}

	// Test the random access feature
	public void TestSet() 
	{
		ConcreteCollection myCollection;
		int numberOfItems;
		numberOfItems = 3;
		myCollection = new ConcreteCollection(numberOfItems);
		IList listObj = myCollection;
		listObj[0] = 99;
		Assert((int) listObj[0] == 99);
		Assert(myCollection.onSetFired);
		Assert(myCollection.onSetCompleteFired);
		Assert(myCollection.onSetOldValue == 0);
		Assert(myCollection.onSetCompleteOldValue == 0);
		Assert(myCollection.onSetNewValue == 99);
		Assert(myCollection.onSetCompleteNewValue == 99);
	}
}

}
----------------------- CollectionBaseTest.cs ends --------

</pre>
	<ul>
		* If you use Emacs, you might want to use the .emacs 
		  file and the package developed by Brad Merrill 
		  mailto:zbrad@cybercom.net. It will allow you to 
		  highlight and indent in C# style in your Emacs
		  editor. (XEmacs will still work but it'll also 
		  complain).

		* CSharpDevelop is a GPLed IDE developed by IC#Code. 
		  Search for it at sourceforge if you are interested 
		  in it.

		* For those who Java: "A comparison of Microsoft's 
		  C# programming language to Sun Microsystem's Java 
		  Programming language" by Dare Obasanjo is a really good 
		  (very complete) text to read. 

		* Suggest this point and more, now I can't think of 
		  anything more.
	</ul>

	Enjoy!!.

	(c) 2002, <a href="mailto:jaime@geneura.ugr.es">Jaime Anguiano Olarra</a>.

	The parts included in this document are property of their 
	respective authors.

	Note: The identation of the source code has been changed a bit
	so it could fit better in the website. Anyway, as nothing more
	changed, the files should work as expected.