شنبه, ۲۹ اردیبهشت, ۱۴۰۳ / 18 May, 2024
مجله ویستا

روان‌شناسی آزمایش نرم‌افزار


روان‌شناسی آزمایش نرم‌افزار
● مقدمه
آزمایش نرم‌افزار یک کار فنّی است امّا مستلزم ملاحظات مهم اقتصادی و روان‌شناسی نیز می‌باشد.
برنامه‌نویسان در بهترین حالت مایلند که تمام ترکیبات ممکن یک برنامه را مورد آزمایش قرار دهند. امّا در اغلب موارد این امر امکان‌پذیر نیست. حتی یک برنامه ظاهراً ساده هم می‌تواند صدها یا شاید هزاران ترکیب ممکن ورودی و خروجی داشته باشد. ایجاد آزمایه ۱ برای تمام این احتمالات، کاری غیر عملی است. آزمایش کامل یک نرم‌افزار کاربردی پیچیده، به زمان و نیروی انسانی بسیار زیادی نیاز دارد که این امر معمولاً از لحاظ اقتصادی به صرفه نیست.
به‌علاوه آزمونگر ۲ نرم‌افزار باید نگرش و دید مناسبی داشته باشد تا بتواند آزمایش یک نرم‌افزار کاربردی را با موفقیت انجام دهد. در بعضی موارد، نگرش آزمونگر ممکن است حتی از خود فرایند واقعی آزمایش نیز مهمتر باشد. به این جهت، باید پیش از پرداختن به مسائل فنی آزمایش نرم‌افزار، جنبه‌های روان‌شناسانه آن‌را مورد بررسی قرار داد.
● روان‌شناسی آزمایش
یکی از دلایل اصلی آزمایش ضعیف برنامه‌ها این واقعیت است که اغلب برنامه‌نویسان با تعریف اشتباهی از این عبارت کار خود را آغاز می‌کنند. آن‌ها پیش خود فکر می‌کنند:
«آزمایش عبارت است از فرایند نشان دادن عدم وجود خطا». و «یا هدف از آزمایش این است که نشان داده شود برنامه، عملکرد مورد نظر را به درستی انجام می‌دهد». و یا آزمایش عبارت است از فرایند اطمینان یافتن از این‌که برنامه، کاری که باید انجام دهد را انجام می‌دهد».
این تعاریف در واقع وارونه هستند!
هنگامی‌که شما برنامه‌ای را آزمایش می‌کنید، می‌خواهید که ارزشی را به آن بیافزائید. منظور از افزودن ارزش از طریق آزمایش، بالا بردن کیفیت یا اطمینان‌پذیری ۳ برنامه است. و بالا بردن اطمینان‌پذیری برنامه هم به معنی یافتن و برطرف کردن خطاهاست.
بدین‌خاطر، نباید برنامه را آزمایش کرد تا نشان داد درست کار می‌کند، بلکه باید با این فرض که برنامه حاوی خطاست شروع کرد (فرضی که در مورد اغلب برنامه‌ها صادق است) و آنگاه برنامه را برای یافتن خطاهای هرچه بیشتر، مورد آزمایش قرار داد.
بنابراین، تعریف دقیقتری از آزمایش نرم‌افزار چنین است:
آزمایش عبارت است از فرایند اجرای برنامه با هدف یافتن خطاها. هر چند ممکن است این بازی با کلمات به نظر آید امّا وقعاً وجه تمایز مهمی وجود دارد. درک تعریف درست آزمایش نرم‌افزار می‌تواند تفاوت چشمگیری در موفقیت تلاش‌های شما در این زمینه به‌وجود آورد.
انسان تمایل شدید به هدف‌گرایی دارد و قرار دادن هدف مناسب، دارای تأثیر روانی مهمی است. اگر هدف ما این باشد که نشان دهیم برنامه خطا ندارد، به طور ناخودآگاه به سمت این هدف هدایت می‌شویم. یعنی داده‌های آزمایشی‌ای را انتخاب می‌کنیم که احتمال کمتری دارد تا باعث عملکرد اشتباه برنامه گردند. امّا از سوی دیگر، چنانچه هدف ما نشان دادن این باشد که برنامه دارای خطاست، آنگاه داده‌های آزمایشی ما نیز احتمال بیشتری دارد که باعث کشف خطاها گردند. این رویکرد دوم نسبت به اولی، ارزش بیشتری را به برنامه می‌افزاید.
این تعریف از آزمایش نرم‌افزار دارای تأثیرات و معانی ضمنی بسیاری است. برای مثال، بیانگر این‌است که آزمایش، فرایند مخرب و حتی آزاردهنده‌ای می‌باشد و به همین دلیل است که برای اغلب مردم دشوار است. دیدگاه و نگرش اغلب ما نسبت به زندگی، سازنده است نه مخرّب. در‌حالی‌که با این تعریف، نتیجه یک فرایند آزمایش موفق، کاملاً برخلاف تمایل قلبی ما خواهد بود. این تعریف همچنین برروی چگونگی طراحی آزمایه‌ها و داده‌های آزمایشی و نیز این‌که چه‌کسی باید یک برنامه را آزمایش کند و چه‌کسی نباید، تأثیر‌گذار است.
راه دیگری که برای تحکیم تعریف مناسبی از آزمایش نرم‌افزار وجود دارد، تحلیل استفاده از واژه‌های «موفق» و «ناموفق»، به‌ویژه استفاده از آن‌ها توسط مدیران پروژه در رده‌بندی نتایج آزمایه‌ها، می‌باشد. اغلب مدیران پروژه، آزمایه‌ای که خطایی نیافته است را «موفق» و برعکس آن‌را «ناموفق» می‌خوانند.
یکبار دیگر باید بگوئیم که این تعبیر کاملاً وارونه است! واژه «ناموفق» نشانگر یک چیز نامطلوب یا ناراحت‌کننده است. در‌حالی‌که بنا به تعریفی که از آزمایش نرم‌افزار ارائه شد، یک آزمایش خوب سازماندهی شده و خوب اجرا شده هنگامی موفق است که به یافتن خطاهایی که قابل اصلاح باشند بیانجامد. چنانچه همین آزمایش نهایتاً به اثبات رساند که دیگر خطایی برای یافتن وجود ندارد آنگاه باید آن‌را آزمایش موفقی نامید. امّا آزمایش ناموفق، آزمایشی است که نرم‌افزار را به طور مناسب مورد بررسی قرار ندهد. در اغلب موارد، آزمایشی که خطایی نیابد را باید ناموفق خواند زیرا مفهوم برنامه بدون خطا اساساً مفهومی غیر‌واقعی است.
اگر این تعبیر را به طراحی آزمایه‌ها تعمیم دهیم باید بگوئیم آزمایه‌ای که منجر به یافتن یک خطای جدید شده است را به‌هیچ‌وجه نباید ناموفق نامید، بلکه برعکس باید ارزش زیادی برای آن قائل شد. یک آزمایه ناموفق آزمایه‌ای است که باعث شود برنامه، بدون یافتن هیچ خطایی، جواب درست تولید کند.
در مقام مقایسه، فردی را در نظر بگیرید که به پزشک مراجعه می‌کند و به او می‌گوید که حالش خوب نیست و نوعی حس کسالت عمومی دارد. اگر پزشک چند نوع آزمایش برای آن فرد بنویسد و نتایج آزمایش‌ها نشان دهنده مشکلی نباشند، ما آن آزمایش‌ها را «موفقیت‌آمیز» نمی‌نامیم زیرا او متحمل مقداری هزینه شده و کسالتش نیز همچنان پابرجاست. امّا اگر نتیجه آزمایش نشان دهد که فرد زخم معده دارد، آن آزمایش موفقیت‌آمیز بوده است زیرا اکنون پزشک می‌تواند به درمان مناسب بپردازد. به‌همین‌خاطر است که پزشکان معمولاً واژه‌های «موفق» و «ناموفق» (یا مثبت و منفی) را در این مورد درست به‌کار می‌برند. مقایسه‌ای که در اینجا وجود دارد این است که ما نیز برنامه‌ای که می‌خواهیم شروع به آزمایشش کنیم را باید به مثابه یک فرد بیمار در نظر بگیریم.
مشکل دومی که با تعریف آزمایش به‌عنوان «فرایند نشان‌دادن عدم وجود خطا» پیش می‌آید این‌است که دستیابی به چنین هدفی، تقریباًٌ برای تمام برنامه‌ها حتی برنامه‌های کوچک و ساده، غیرممکن است.
باز هم مطالعات روان‌شناسی به ما می‌گوید که انسان‌ها هنگامی‌که به انجام دادن کاری گمارده می‌شوند که می‌دانند غیرممکن و دست نیافتنی است، عملکرد ضعیفی از خود بروز می‌دهند. برای مثال، اگر از فردی خواسته شود که یک جدول سخت را ظرف ۱۵ دقیقه حل کند، معمولاً بعد از گذشت ۱۰ دقیقه یا هیچ پیشرفتی در حل جدول دیده نمی‌شود و یا پیشرفت بسیار کمی دیده می‌شود زیرا اغلب افراد در مقابل کاری که غیرممکن به نظر می‌رسد تسلیم می‌شوند و دست از تلاش بر‌می‌دارند. امّا اگر از آن فرد خواسته شود که همان جدول را در چهار ساعت حل کند، بعد از گذشت ۱۰ دقیقه پیشرفت بیشتری نسبت به حالت اوّل دیده خواهد شد. بنابراین درنظر گرفتن آزمایش نرم‌افزار به‌عنوان فرایند کشف خطاهای برنامه، آن‌را به‌صورت کاری امکانپذیر جلوه می‌سازد و این مشکل روانی را نیز از میان برمی‌دارد.
سومین مشکلی که با تعریف آزمایش نرم‌افزار به‌صورت «فرایند نشان دادن این‌که برنامه کاری که باید انجام دهد را انجام می‌دهد» وجود دارد این‌است که برنامه‌هایی که این‌چنین هستند، یعنی کاری که باید انجام دهند را انجام می‌دهند، نیز هنوز ممکن است دارای خطا باشند. به‌عبارت دیگر، اگر برنامه‌ای کاری که باید انجام دهد را انجام ندهد، واضح است که خطایی در آن وجود دارد امّا اگر برنامه‌ای کاری که نباید انجام دهد را انجام دهد نیز دارای خطاست. اگر ما به آزمایش برنامه به‌صورت فرایند کشف خطاها فکر کنیم، احتمال بیشتری دارد که این نوع خطاها را بیابیم تا آن‌که آن‌را به‌صورت فرایند نشان‌دادن این‌که برنامه کاری که باید انجام دهد را انجام می‌دهد، در نظر بگیریم.
خلاصه آن‌که آزمایش برنامه مناسب‌تر است به‌صورت فرایند تلاش برای کشف خطاهای برنامه (که فرض می‌شود وجود دارند) در نظر گرفته شوند. یک آزمایه موفق، آزمایه‌ای است که در این جهت باعث پیشرفت گردد، یعنی باعث عملکرد اشتباه برنامه شود. البته نهایتاً ما می‌خواهیم که از طریق آزمایش نرم‌افزار به درجه قابل قبولی از اطمینان به این‌که برنامه کاری که باید انجام دهد را انجام می‌دهد و کاری که نباید انجام دهد را انجام نمی‌دهد، برسیم امّا این هدف تنها از طریق جستجوی پیگیرانه خطاها دست یافتنی است.
فرض کنید کسی نزد شما بیاید و ادعا کند که «برنامه‌اش کامل و بی‌نقص است». بهترین راه برای اطمینان یافتن از صحت ادعای او این است که سعی کنیم ادعایش را رد کنیم، یعنی سعی کنیم خطایی در آن بیابیم، نه این‌که صرفاً به‌خاطر این‌که برنامه‌اش با چند داده آزمایشی درست کار می‌کند ادعایش را بپذیریم.
● اصول آزمایش نرم‌افزار
با یادآوری مجدّد این نکته که مهمترین ملاحظه‌ای که در آزمایش نرم‌افزار باید در نظر گرفته شود جنبه‌های روان‌شناسی آن‌است، می‌توان مجموعه‌ای از اصول یا رهنمودهای مهم و ضروری برای آزمایش را به شرح زیر ارائه کرد. هرچند اغلب آن‌ها ممکن است بدیهی به نظر آیند امّا غالباً نادیده گرفته می‌شوند.
▪ اصل ۱: یک بخش ضروری در هر آزمایه، تعریف خروجی یا نتایج مورد انتظار است.
این اصل بدیهی، یکی از شایعترین اشتباهات در آزمایش برنامه‌ها است. این اصل هم بر پایه روان‌شناسی انسان قرار دارد. اگر نتیجه مورد انتظار یک آزمایه از پیش تعریف نشده باشد، احتمال دارد که یک جواب ظاهر فریب ولی اشتباه، به‌عنوان یک جواب صحیح و معتبر تلقی گردد زیرا در روان‌شناسی اصلی وجود دارد با این عنوان که «چشم چیزی را می‌بیند که می‌خواهد». به عبارت دیگر، تمایل ناخودآگاه ما، دیدن جواب صحیح است. یک راه برای مقابله با این تمایل، تعریف دقیق و با جزئیات کامل خروجی مورد انتظار برنامه است. بنابراین، هر آزمایه باید شامل دو بخش باشد:
۱) توصیف داده‌های ورودی برنامه.
۲) تعریف دقیق خروجی صحیح برنامه برای آن مجموعه از داده‌های ورودی.
اگر انتظاراتی وجود نداشته باشد، هیچ چیز ما را شگفت‌زده نخواهد کرد.
▪ اصل ۲: یک برنامه‌نویس باید از آزمایش برنامه‌ای که خودش نوشته است اجتناب کند.
هر نویسنده‌ای می‌داند (یا باید بداند) که سعی در ویرایش یا غلط‌گیری متنی که خودش نوشته، ایده درستی نیست. شما خودتان می‌دانید که آن متن چه چیزی قرار است بگوید و ممکن است اگر واقعاً چیز دیگری را القاء می‌کند نتوانید آن را تشخیص دهید. به‌علاوه، هیچکس نمی‌خواهد در کارهای خود خطایی را کشف کند. چنین موضوعی در مورد نویسندگان نرم‌افزار نیز صادق است.
مشکل دیگری که پیش می‌آید این است که پس از آن‌که برنامه‌نویسی با دید «مثبت» و سازنده به طراحی و کد کردن برنامه‌اش پرداخت، بسیار مشکل است که ناگهان تغییر دیدگاه داده و با چشم «منفی» و تخریبی به آن برنامه بنگرد.
بسیاری از صاحب خانه‌ها می‌دانند که کندن کاغذ دیواری (فرایند تخریبی) کار ساده‌ای نیست امّا همین کار چنانچه کاغذ دیواری‌ها را قبلاً با دستان خودتان چسبانده باشید، بسیار سخت‌تر و ناراحت‌کننده‌تر جلوه می‌کند. به طریق مشابه، بسیاری از برنامه‌نویسان نیز نمی‌توانند برنامه‌های خود را به نحو مؤثری آزمایش کنند زیرا نمی‌توانند با تغییر ذهنیت لازم به منظور یافتن و نشان دادن خطاهای کار خودشان، کنار آیند. به‌علاوه، گاهی اوقات یک برنامه‌نویس به‌طور ناخودآگاه از ترس تحقیر در مقابل همکاران یا مدیر پروژه یا مشتریان، از کشف خطاها اجتناب می‌کند. علاوه‌بر این جنبه‌های روان‌شناسانه، مشکل مهم دیگری نیز وجود دارد و آن این‌که خطاهای برنامه ممکن است به علّت درک نادرست مشخصات ۴ مسأله از سوی برنامه‌نویس باشد. در این صورت، برنامه‌نویس همان درک نادرست خود را به آزمایش برنامه خودش نیز منتقل خواهدکرد.
البته این بدان معنی نیست که آزمایش برنامه توسط خود برنامه‌نویس امکانپذیر نیست. بلکه اگر کس دیگری آزمایش را انجام دهد، مؤثرتر و موفقیت‌آمیزتر خواهد بود.
توجه داشته باشید که این مسأله در مورد اشکالزدایی ۵ (تصحیح خطاهای یافته شده) صادق نیست. اشکالزدایی توسط برنامه‌نویس اولیه بسیار مؤثرتر است.
▪ اصل ۳: یک نهاد برنامه‌نویسی نباید برنامه‌های خود را آزمایش کند.
استدلالی که در این مورد وجود دارد مشابه اصل قبلی است. سازمان پروژه، از بسیاری جهات، همانند یک موجود زنده است با همان مشکلات روانی که برای یک برنامه‌نویس منفرد وجود دارد. به‌علاوه، در اغلب محیط‌ها کار یک نهاد برنامه‌نویسی یا یک مدیر پروژه عمدتاً بر اساس توانایی تولید نرم‌افزار در یک زمان مشخص و با یک هزینه خاص، مورد ارزیابی قرار می‌گیرد. یک دلیلش این‌است که اندازه‌گیری زمان وهزینه مصرف شده آسان است امّا اندازه‌گیری قابلیت اطمینان یک برنامه و کمّی کردن آن بسیار دشوار می‌باشد. به این جهت، برای یک نهاد برنامه‌نویسی، مشکل است که به آزمایش واقعگرایانه و جدّی برنامه‌هایی که خود تولید کرده بپردازد زیرا فرایند آزمایش اگر بخواهد با تعریف درست انجام شود، احتمال اتمام پروژه در موعد مقرّر و با هزینه معیّن را کاهش خواهد داد.
باز هم تکرار می‌کنیم که برای یک نهاد برنامه‌نویسی غیر ممکن نیست که خطاهای برنامه‌های خود را کشف کند امّا انجام این‌کار توسط یک نهاد مستقل، بهتر و اقتصادی‌تر است.
▪ اصل ۴: نتایج هر آزمایش را به دقت مورد بررسی قرار دهید.
این احتمالاً واضح‌ترین و بدیهی‌ترین اصل است امّا این اصل هم معمولاً نادیده گرفته می‌شود. ما بارها شاهد بوده‌ایم که بسیاری از خطاها، حتی با وجودی که رد پای آن‌ها به وضوح در لیست خروجی‌ها قابل مشاهده بوده، یافته نشده‌اند. به عبارت دیگر، خطاهایی که در آزمایش‌های بعدی یافت می‌شوند غالباً آن‌هایی هستند که در بررسی نتایج آزمایش‌های قبلی نادیده گرفته شده بودند.
▪ اصل ۵: آزمایه‌ها باید هم برای ورودی‌های معتبر و مورد انتظار و هم برای ورودی‌های نامعتبر و غیر منتظره نوشته شوند.
تمایل طبیعی به هنگام آزمایش برنامه، تمرکز بر وضعیت‌های معتبر و مورد انتظار ورودی‌ها است و این گاهی باعث غفلت از وضعیت‌های غیر منتظره و نامعتبر می‌شود. معمولاً آزمایه‌هایی که بیانگر این‌گونه وضعیت‌ها هستند، خطاهای بیشتری را نسبت به آزمایه‌های شرایط معتبر ورودی کشف می‌کنند.
▪ اصل ۶: آزمایش برنامه به‌منظور بررسی این‌که برنامه کاری که باید انجام دهد را انجام می‌دهد یا نه، تنها یک بخش از کار است. بخش دیگر، باید بررسی این باشد که برنامه کاری که نباید انجام دهد را انجام می‌دهد یا نه.
این اصل نتیجه منطقی اصل قبلی است. برنامه‌ها باید برای اثرات جانبی ناخواسته، مورد بررسی و آزمایش قرار بگیرند. برای مثال، یک برنامه حقوق و دستمزد که برگه‌های حقوق را به‌صورت صحیح تولید می‌کند هنوز ممکن است دارای خطا باشد. مثلاً برگه‌های حقوق اضافی برای کارمندانی که وجود ندارند تولید کند و یا روی نخستین رکورد پرونده کارکنان، اطلاعاتی را به اشتباه بنویسد.
▪ اصل ۷: آزمایه‌ها را هرگز دور نیاندازید مگر آن‌که خود برنامه، دور‌انداختنی باشد.
این مسأله معمولاً در مورد سیستم‌های تعاملی ۶ که برای آزمایش برنامه‌ها به‌کار می‌روند پیش می‌آید. یک روش متداول این است که فرد در پشت پایانه می‌نشیند و آزمایه‌ها را فی‌البداهه می‌سازد و سپس برنامه‌ها را با آن‌ها مورد آزمایش قرار می‌دهد. مشکل اصلی این است که آزمایه‌ها که سرمایه باارزشی هستند، در این محیط پس از تکمیل شدن آزمایش، از بین می‌روند. هرگاه لازم باشد که برنامه دوباره مورد آزمایش قرار گیرد (مثلاً پس از تصحیح یک خطا یا افزودن یک قابلیت تازه)، آزمایه‌ها باید دوباره از نو ساخته شوند. و چون این‌کار معمولاً زمان قابل ملاحظه‌ای می‌گیرد، مردم از آن اجتناب می‌کنند. به این جهت، آزمایش مجدّد برنامه، ندرتاً به دقت و کاملی آزمایش اولیه صورت می‌گیرد و این بدان معنی است که چنانچه اصلاحات باعث شود که بخشی از برنامه که قبلاً عملیاتی بود دچار مشکل و خطا گردد، این خطا غالباً کشف نشده باقی می‌ماند. نگهداری آزمایه‌ها و اجرای مجدّد آن‌ها پس از اعمال تغییرات در مؤلفه‌های دیگر برنامه را آزمایش پسنمائی ۷ می‌نامند.
▪ اصل ۸: آزمایش نرم‌افزار را با این فرض اشتباه که خطایی یافته نخواهد شد، برنامه‌ریزی نکنید.
این اشتباهی‌است که غالباً مدیران پروژه انجام می‌دهند و نشانه‌ای است از کاربرد تعریف نادرست آزمایش. یعنی این فرض که آزمایش عبارت است از فرایند نشان دادن این‌که برنامه درست کار می‌کند. یکبار دیگر تأکید می‌کنیم که تعریف آزمایش، فرایند اجرای برنامه با نیّت یافتن خطاها است.
▪ اصل ۹: احتمال وجود خطاهای بیشتر در یک بخش از برنامه، متناسب است با تعداد خطاهایی که تا کنون در آن بخش یافته شده است.
طریقه دیگری برای بیان این اصل این است که بگوئیم خطاها معمولاً به صورت خوشه‌ای پدید می‌آیند و این‌که در برنامه‌های معمولی، بعضی از بخش‌ها نسبت به سایر بخش‌ها بیشتر مستعد خطا هستند. هرچند، هیچکس تا‌کنون توضیح مناسب و جالبی درباره این‌که چرا این‌گونه است، ارائه نکرده است. آگاهی از این پدیده، اطلاعات با ارزشی درباره فرایند آزمایش در اختیار ما می‌گذارد. اگر در بخشی از برنامه، خطاهای بیشتری نسبت به سایر بخش‌ها یافته شد، آنگاه این پدیده به ما می‌گوید که بهتر است تلاش جداگانه‌ و ویژه‌ای بر روی آزمایش آن بخش متمرکز گردد.
▪ اصل ۱۰: آزمایش نرم‌افزار، کار بسیار خلاقانه و از نظر ذهنی چالش برانگیزی است.
این جمله احتمالاً درست است که خلاقیت مورد نیاز برای آزمایش یک برنامه بزرگ، بیشتر از خلاقیت مورد نیاز برای طراحی آن برنامه است. ما تا‌کنون متوجه شده‌ایم که تضمین عدم وجود خطا از طریق آزمایش امکانپذیر نیست. طراحی آزمایه‌های مناسب برای پوشش دادن بیشتر وضعیت‌های امکانپذیر برای یک برنامه، به مقدار زیادی خلاقیت نیاز دارد.
● نتیجه گیری
به هنگام آزمایش نرم‌افزار، همیشه این سه اصل مهم را در نظر داشته باشید:
۱) آزمایش عبارت است از فرایند اجرای یک برنامه با هدف یافتن خطاها.
۲) یک آزمایه خوب آزمایه‌ای است که احتمال زیادی داشته باشد که خطاهایی که تا‌کنون یافته نشده‌اند را کشف کند.
۳) یک آزمایه موفق آزمایه‌ای است که یک خطای تاکنون کشف نشده را بیابد.
ترجمه ابراهیم نقیب‌زاده مشایخ
منبع
این مطلب، ترجمه بخشی از فصل دوم کتاب زیر است:
“ The Art of Software Testing ” , Glenford J. Myers Second Edition, John Wiley Sons, Inc., ۲۰۰۴.
۱) test case
۲) tester
۳) reliability
۴) specification
۵) debugging
۶) interactive
۷) regression testing
۸) module
۹) class
۱۰) subroutine
منبع : دوماهنامه گزارش کامپیوتر