آموزش جامع برنامه نویسی جاوا به زبان ساده — بخش هفتم: حالت تست
در بخشهای قبلی از سلسله آموزشهای برنامه نویسی جاوا در مورد مقدمات این زبان و مفاهیم پایه شیءگرایی آموختیم و نخستین کلاس جاوا را نوشتیم. اینک در این بخش کلاس خود را تست خواهیم کرد.
بخش چهارم: آشنایی با زبان جاوا
ایجاد حالت تست JUnit
ابتدا از طریق وارد کردن قطعه کد 5 در پنجره سورس و در زیر بخش تعریف کلاس (خط پس از public class Person)، سازنده را به کلاس Person اضافه میکنیم.
قطعه کد 5- سازنده کلاس
public Person(String name, int age, int height, int weight, String eyeColor, String gender) {
this.name = name;
this.age = age;
this.height = height;
this.weight = weight;
this.eyeColor = eyeColor;
this.gender = gender;
}
مطمئن شوید که خط موجداری که نشاندهنده خطاهای کامپایلر باشد ندارید.
اینک حالت تست JUnit را که در آن یک وهله از کلاس Person را با استفاده از سازنده در قطعه کد 5 میسازیم ایجاد میکنیم و سپس حالت شیء را در کنسول پرینت میکنیم. در این وضعیت تست مطمئن میشود که ترتیب خصوصیات در فراخوانی سازنده صحیح است (یعنی خصوصیات صحیحی در آن قرار گرفتهاند).
در پکیج اکسپلورر بر روی کلاس Person راست کلیک میکنیم و سپس New > JUnit Test Case را انتخاب میکنیم. صفحه نخست ویزارد حالت تست JUnit جدید مانند شکل زیر است.
ایجاد یک حالت تست JUnit
با کلیک Next مقادیر پیشفرض را میپذیریم. صفحه متدهای تست که در شکل بعدی به تصویر کشیده شده است نمایش مییابد.
انتخاب متدها برای ویزارد ایجاد حالتهای تست
در این صفحه متد یا متدهایی که میخواهید حالت تست برایشان ساخته شوند انتخاب میکنید. در این مورد همانطور که در شکل بالا مشخص شده است تنها سازنده (constructor) را انتخاب میکنیم. بر روی Finish کلیک کنید تا ایکلیپس حالت تست JUnit را ایجاد کند.
سپس PersonTest را باز کنید و به متد ()testPerson بروید و آن را شبیه قطعه کد 6 بنویسید.
قطعه کد 6- متد ()testPerson
@Test
public void testPerson() {
Person p = new Person("Joe Q Author", 42, 173, 82, "Brown", "MALE");
Logger l = Logger.getLogger(Person.class.getName());
l.info("Name: " + p.getName());
l.info("Age:" + p.getAge());
l.info("Height (cm):" + p.getHeight());
l.info("Weight (kg):" + p.getWeight());
l.info("Eye Color:" + p.getEyeColor());
l.info("Gender:" + p.getGender());
assertEquals("Joe Q Author", p.getName());
assertEquals(42, p.getAge());
assertEquals(173, p.getHeight());
assertEquals(82, p.getWeight());
assertEquals("Brown", p.getEyeColor());
assertEquals("MALE", p.getGender());
}
فعلاً در مورد کلاس Logger نگران نباشید. کافی است کد را وارد کنید تا مانند قطعه کد 6 به نظر برسد. اینک برنامه جاوا (و حالت تست JUnit) آماده اجرا است.
اجرای حالت تست در ایکلیپس
در ایکلیپس بر روی PersonTest.java در پکیج اکسپلورر راست کلیک کنید و Run As > JUnit Test را انتخاب کنید. شکل زیر آنچه را که رخ میدهد نشان داده است.
اجرای Person
نمای کنسول بهطور خودکار باز میشود و خروجی Logger را نشان میدهد و نمای JUnit نشان میدهد که تست بدون خطا اجرا شده است.
افزودن رفتار به کلاس جاوا
تا اینجا کلاس Person خوب به نظر میرسد اما می تون چند رفتار دیگر نیز به آن اضافه کرد تا جالبتر شود. ایجاد رفتار به معنی افزودن متد است. در این بخش به بررسی متدهای دسترسی، getter و setter که قبلاً اشاره کردیم میپردازیم.
متدهای دسترسی
متدهای getter و setter که در بخشهای قبل اشاره کردیم به نام متدهای دسترسی Accessor نامیده میشوند. (getter متدی برای دریافت مقادیر از یک خصوصیت و setter متدی برای اصلاح این مقادیر است.) برای کسپولهسازی دادههای یک کلاس از اشیای دیگر باید متغیرها را بهصورت private تعریف کنیم و سپس متدهای دسترسی تعریف کنیم.
نامگذاری متدهای دسترسی از قواعد مشخصی پیروی میکند که به الگوی JavaBeans مشهور است. در این الگو هر خصوصیتی برای مثال Foo یک متد getter به نام ()getFoo و یک متد setter به نام ()setFoo دارد. الگوی JavaBeans چنان رایج است که IDE ایکلیپس نیز از آن پشتیبانی میکند و در هنگام ایجاد متدهای دسترسی برای کلاس Person این را میبینیم.
متدهای دسترسی از این اصول تبعیت میکنند:
- خصوصیت همواره با دسترسی private تعریف میشود.
- تعیین سطح دسترسی برای متدهای getter و setter بهصورت public است.
- متد getter هیچ پارامتری نمیگیرد و مقداری بازمیگرداند که نوع آن همان نوع خصوصیت مورد دسترسی است.
- Setter تنها یک پارامتر میگیرد که از نوع خصوصیت است و مقدار بازگشتی ندارد.
اعلانهای دسترسی
آسانترین روش اعلان متدهای دسترسی این است که اجازه دهیم ایکلیپس این کار را انجام دهد. اما لازم است که نحوه نوشتن دستی این کدها را نیز یاد بگیرید.
فرض کنید خصوصیتی به نام Foo داریم که نوع آن java.lang.String است. اعلان کامل برای Foo چنین است:
private String foo;
public String getFoo() {
return foo;
}
public void setFoo(String value) {
foo = value;
}
توجه داشته باشید که مقدار پارامتری که به setter ارسال میشود، وقتی متد را ایکلیپس ایجاد میکند نام متفاوتی با خصوصیت دارد در حالی که این مقدار باید همنام با خصوصیت باشد برای مثال (public void setFoo(String foo. هنگام کد نویسی دستی باید سعی کنیم این مقدار همواره با نام خصوصیت یکسان باشد چون این روش که همیشه به توسعهدهندهها توصیه میشود موجب میشود که متوجه بشویم این کد را دستی نوشتهایم. اگر لازم بوده است که از کد ایجادشده توسط ایکلیپس استفاده نکنیم حتماً دلیل خوبی برای این کار داشتهایم. استفاده از نام value برای پارامتر setter به خاطرمان میآورد که این setter خاص است. البته میتوان از توضیحات در متن کد نیز استفاده کرد.
فراخوانی متدها
فراخوانی متدها آسان است. برای مثال متد testPerson در قطعه کد 6، getter های مختلف Person را برای بازگرداندن مقادیرشان فراخوانی میکند. اینک یاد میگیریم که سازوکار رسمی ایجاد فراخوانی متدها چگونه است.
فراخوانی متد با یا بدون پارامتر
برای فراخوانی یک متد بر وی یک شیء باید به آن شیء ارجاع بدهیم. دستورزبان فراخوانی متد شامل موارد زیر است:
- ارجاع شیء
- علامت نقطه
- نام متد
- هر پارامتری که باید ارسال شود.
دستور زبان فراخوانی متد بدون پارامتر چنین است:
objectReference.someMethod();
در ادامه مثالی ارائه شده است:
Person p = new Person("Joe Q Author", 42, 173, 82, "Brown", "MALE");
p.getName();
دستورزبان فراخوانی متد با پارامتر بهصورت زیر است:
objectReference.someOtherMethod(parameter1, parameter2,..., parameterN);
و نمونهای از آن (تعیین خصوصیت نام Person):
Person p = new Person("Joe Q Author", 42, 173, 82, "Brown", "MALE");
p.setName("Jane Q Author");
به یاد داشته باشید که سازندهها نیز نوعی متد هستند. میتوانید پارامترها را با زدن دکمه space یا ENTER از هم جدا کنید. کامپایلر جاوا اهمیتی به این تفاوت نمیدهد. دو فراخوانی متد با هم یکسان هستند.
new Person("Joe Q Author", 42, 173, 82, "Brown", "MALE");
یا به صورت جزییتر:
new Person("Joe Q Author", // Name
42, // Age
173, // Height in cm
82, // Weight in kg
"Brown", // Eye Color
"MALE"); // Gender
توجه کنید که چگونه توضیحات در متد دوم آن را برای کسی که ممکن است بعداً با آن کار کند، خواناتر کرده است. آن توسعهدهنده با یک نگاه میتواند بگوید که هر پارامتر برای چه تعریف شده است.
فراخوانیهای متد تودرتو
فراخوانیهای متد میتوانند بهصورت تودرتو باشند:
Logger l = Logger.getLogger(Person.class.getName());
l.info("Name: " + p.getName());
در اینجا مقدار بازگشتی ()Person.class.getName را به متد ()getLogger میفرستد. به یاد داشته باشید که فراخوانی متد ()getLogger یک فراخوانی متد استاتیک است. بنابراین دستورزبان آن اندکی متفاوت است. (لازم نیست که برای فراخوانی ارجاع Logger داشته باشید؛ در عوض از نام کلاسی که در سمت چپ فراخوانی است استفاده میکنیم.)