<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
    <channel>
        <title>نوشته های محدثه سالم</title>
        <link>https://virgool.io/feed/@mohsal110</link>
        <description>صفحه ی لینکدین من:    https://www.linkedin.com/in/mohaddese-salem-27388318b</description>
        <language>fa</language>
        <pubDate>2026-06-07 04:41:31</pubDate>
        <image>
            <url>https://files.virgool.io/upload/users/609659/avatar/GfOgi7.jpeg?height=120&amp;width=120</url>
            <title>محدثه سالم</title>
            <link>https://virgool.io/@mohsal110</link>
        </image>

                    <item>
                <title>نصب Nginx روی Ubuntu و Windows</title>
                <link>https://virgool.io/@mohsal110/%D9%86%D8%B5%D8%A8-nginx-%D8%B1%D9%88%DB%8C-ubuntu-hrc732bhwhml</link>
                <description>در این مقاله، میخواهیم مراحل نصب Nginx روی Ubuntu را قدم به قدم طی کنیم. امیدوارم این مقاله، براتون مفید باشه.پکیج Nginx روی مخازن پیشفرض Ubuntu وجود دارد. بنابراین اجرای دستورات زیر آخرین نسخه از Nginx و پکیج های وابسته به آن را روی سیستم عامل Ubuntu نصب می‌کند.$ sudo apt update
$ sudo apt install nginxسرویس Nginx پس از نصب در Ubuntu به صورت خودکار اجرا می‌شود. دستور زیر وضعیت این سرویس را نمایش می‌دهد.$ sudo systemctl status nginxاگر Nginx با موفقیت نصب شده باشد، پس از اجرای دستور بالا با خروجی ای شبیه به تصویر زیر مواجه خواهید شد که نشان می‌دهد این سرویس فعال و در حال اجرا روی سیستم است.در صورت نیاز به متوقف کردن سرویس Nginx می‌توانید از دستور زیر استفاده کنید:$ sudo systemctl stop nginxبرای راه اندازی این سرویس وقتی که در حالت توقف است، از دستور زیر استفاده می‌شود:$ sudo systemctl start nginxزمانی که تنظیمات Nginx تغییر می‌کند، برای اعمال تغییرات می‌توانید این سرویس را Restart کنید. این کار معادل Stop و سپس Start کردن سرویس است:$ sudo systemctl restart nginxزمانی که Nginx را Restart می‌کنید، همه درخواست هایی که در حال پردازش بوده اند قطع (Drop) شده و تا زمان کامل شدن فرآیندِ اجرای مجددِ سرویس، هیچ درخواستی پاسخ داده نمی‌شود. برای اینکه بدون Down شدن سایت یا سرویس های آن بتوانیم تغییرات Nginx را اعمال کنیم، می‌توان به جای Restart از Reload استفاده کرد. در این صورت درخواست هایی که در حال اجرا هستند با تنظیمات قدیم و درخواست های جدید با تنظیمات جدید پاسخ داده می‌شوند.$ sudo systemctl reload nginxسرویس Nginx پس از نصب در Ubuntu به صورت پیش‌فرض Enable است. به این معنی که هر بار که سیستم عامل (کامپیوتری که Nginx روی آن نصب شده) Restart شود، این سرویس به صورت خودکار اجرا می‌شود. در صورت نیاز به Disable کردن این سرویس می‌توان از دستور زیر استفاده کرد:$ sudo systemctl disable nginxو همینطور برای Enable کردن آن در صورت Disable بودن، از دستور زیر استفاده می‌شود:$ sudo systemctl enable nginxبررسی صحت عملکرد Nginxحال که Nginx را نصب کرده و وضعیت این سرویس را بررسی کردید می‌توانید عملکرد آن را تست کنید. Nginx به صورت پیش‌فرض محتوای Static موجود در آدرس var/www/html/ را که فعلا فقط یک فایل HTML است، سرو می‌کند. بنابراین با وارد کردن آدرس IP سرور خود در مرورگر وب باید این صفحه را دریافت کنید که نشان‌دهنده کارکرد صحیح Nginx است. صفحه Landingپیشفرض برای بررسی صحت عملکرد Nginxاگر با وارد کردن آدرس IP سرور در مرورگر، صفحه Landing بالا را مشاهده نکردید، ممکن است Firewall نصب شده روی سرور، اجازه دسترسی به سرور از طریق پورت HTTP (پورت ۸۰) را نمی‌دهد. بنابراین پس از چک کردن درستی آدرس IP و همینطور بررسی وضعیت سرویس، از باز بودن پورت ۸۰ روی سرور نیز مطمین شوید. نحوه تغییردادن تنظیمات Nginx از جمله پورت مورداستفاده‌ی آن، در مقاله‌های بعدی آمده است. راه اندازی Nginx روی ویندوزبرای استفاده از nginx روی ویندوز، تنها کافی است فایل nginx.exe را اجرا کنید. فایل تنظیمات nginx روی ویندوز، در پوشه ی conf قرار دارد.برای مدیریت اجرای nginx، میتوانید از دستورات زیر استفاده کنید:nginx   -s stop         &amp;quotfast   shutdown&amp;quotnginx   -s quit          &amp;quotgraceful   shutdown&amp;quotnginx   -s reload         &amp;quotchanging   configuration, starting new worker processes with a new   configuration,   graceful shutdown of old worker processes&amp;quotnginx   -s reopen      &amp;quotre-opening   log files&amp;quot</description>
                <category>محدثه سالم</category>
                <author>محدثه سالم</author>
                <pubDate>Wed, 18 Sep 2024 15:59:42 +0330</pubDate>
            </item>
                    <item>
                <title>مقدمه‌ای درباره Nginx</title>
                <link>https://virgool.io/@mohsal110/%D9%85%D9%82%D8%AF%D9%85%D9%87-%D8%A7%DB%8C-%D8%AF%D8%B1%D8%A8%D8%A7%D8%B1%D9%87-nginx-p2tj8puaxnum</link>
                <description>نرم‌افزار Nginx در واقع یک وب‌سرور (Web Server) است که می‌تواند به‌عنوان پراکسی معکوس (Reverse Proxy)، توزیع‌کننده بار (Load Balancer) یا کش وب (Web Cache) نیز مورد استفاده قرار گیرد. در این مقاله، عملکردهای مختلف Nginx را به‌صورت خلاصه مرور می‌کنیم. امیدوارم براتون مفید باشه.تعریف وب‌سرور (Web Server)وب‌سرور یا سرور HTTP نرم‌افزاری است که بر روی یک سرور سخت‌افزاری نصب می‌شود و درخواست‌های ارسالی از کلاینت‌ها را در بستری مانند HTTP دریافت و به آنها پاسخ می‌دهد. این پاسخ‌ها یا به صورت ایستا (Static) از قبل در مسیری روی سرور ذخیره شده‌اند یا به صورت پویا (Dynamic) توسط یک برنامه وب تولید می‌شوند و به سمت کلاینت‌ها ارسال می‌گردند. به‌عنوان مثال، فایل‌های تصویری، ویدئوها یا فایل‌های CSS و JavaScript می‌توانند به‌صورت ایستا روی سرور ذخیره و توسط وب‌سرور به کلاینت ارسال شوند. اما اطلاعاتی مانند محصولات خریداری شده توسط کاربر، دانشجویان برتر ترم جاری یا آگهی‌های منقضی‌شده باید به‌صورت لحظه‌ای و پویا از دیتابیس‌ها گردآوری و در قالب یک پاسخ مناسب به کلاینت‌ها ارسال شوند.تعریف پراکسی معکوس (Reverse Proxy)یک سرور پراکسی در حالت عادی واسطه‌ای میان یک کلاینت و سایر سرورها است. این سرور واسط، تمام درخواست‌های کلاینت را دریافت و به سرورهای مقصد ارسال می‌کند. اما پراکسی معکوس برعکس این عملکرد است؛ به‌جای اینکه مانند پراکسی معمولی (Forward Proxy) درخواست‌های کلاینت به سرورهای مختلف ارسال شود، پراکسی معکوس درخواست‌های تمام کلاینت‌ها را دریافت کرده و به یک سرور خاص ارسال می‌کند.تعریف توزیع‌کننده بار (Load Balancer)با افزایش تعداد درخواست‌های ارسالی به یک سرور، منابع بیشتری از سرور اشغال می‌شود و بار (Load) آن افزایش می‌یابد. با افزایش بار روی سرور، عملکرد آن دچار افت شده و پاسخ‌دهی به درخواست‌ها کند می‌شود. در این شرایط سرورهای فعلی پاسخگوی نیاز نیستند و باید سرورها را توسعه دهیم (Scale). شاید اولین راه‌حل افزایش قدرت پردازنده و حافظه باشد که به این روش &quot;اسکیل عمودی&quot; (Vertical Scaling) گفته می‌شود. اما روش بهتر معمولاً استفاده از &quot;مزرعه سرور&quot; (Server Farm) است که در آن چندین سرور با توان متوسط به‌جای یک سرور قوی استفاده می‌شود و به این روش &quot;اسکیل افقی&quot; (Horizontal Scaling) گفته می‌شود. در این حالت، توزیع‌کننده بار (Load Balancer) با قرار گرفتن در جلوی ورودی مزرعه سرور، درخواست‌های ورودی را بین چند سرور توزیع می‌کند.تعریف کش وب (Web Cache)ارائه محتوای ایستا توسط وب‌سرورها بسیار ساده‌تر و سریع‌تر از محتوای پویا است. برای تولید محتوای پویا معمولاً باید کوئری‌های زمان‌بر به دیتابیس‌ها ارسال شود یا الگوریتم‌های پیچیده‌ای اجرا شوند. به همین دلیل، تولید چنین محتوایی کندتر است و منابع سخت‌افزاری بیشتری از سرور را اشغال می‌کند. کش وب یا کش HTTP محتوای پویا که برای درخواست‌های پرتکرار تولید شده را به‌صورت ایستا ذخیره می‌کند و در درخواست‌های بعدی از آن استفاده می‌شود. این کار باعث می‌شود که پاسخ‌دهی به این درخواست‌ها بسیار سریع‌تر انجام شده و همچنین بار (Load) روی سرور به‌طور چشمگیری کاهش یابد.</description>
                <category>محدثه سالم</category>
                <author>محدثه سالم</author>
                <pubDate>Wed, 18 Sep 2024 15:48:21 +0330</pubDate>
            </item>
                    <item>
                <title>تست یکپارچگی</title>
                <link>https://virgool.io/@mohsal110/%D8%AA%D8%B3%D8%AA-%DB%8C%DA%A9%D9%BE%D8%A7%D8%B1%DA%86%DA%AF%DB%8C-jmzzttkqcqiy</link>
                <description>تست یکپارچگیبرای صحبت درباره‌ی تست یکپارچگی،‌ ابتدا لازم است بدانیم منظور ما از یکپارچگی چه چیزی است. مفهومی یکپارچگی (integrity) در سیستم‌های کامپیوتری این است که بدانیم آیا هر بخشی از سیستم (که از قبل مطمئنیم خوب و درست کار می‌کند) می‌تواند در تعامل با سایر بخش‌ها هم درست کار کند؟ آیا در هنگام دریافت ورودی از بخش‌های دیگر،‌ زبان آنها را می‌فهمد؟! یا زمانیکه می‌خواهد خروجی تولید کند؛‌ این خروجی را به طوری تولید می‌کند که برای ماژولهای دیگر نیز قابل فهم و قابل استفاده باشد یا نه؟! آیا عملکرد یک ماژول می‌تواند تاثیر مخربی برای بقیه‌ی ماژول‌ها داشته باشد؟ فرآیندهای تست یکپارچگی به ما کمک می‌کنند تا به این سوال و چندین سوال دیگر پاسخ بدهیمتفاوت تست یکپارچگی با Unit Testمشکلات یکپارچه سازی (Integration)شاید در نگاه اول و از دید فردی که در حوزه‌ی نرم‌افزارهای Enterprise  تجربه‌ای نداشته است،‌ اگر هرکدام از ماژول‌ها یا بخش‌های نرم‌افزار، به تنهایی خوب و درست کار کنند؛ قاعدتا در صورتیکه وارد سیستم شوند و با ماژول‌های دیگر در رابطه باشند هم درست کار میکنند و مشکلی پیش نخواهد آمد. اما در واقعیت اینطور نیست! بلکه وصل کردن ماژول‌های مختلف یک سیستم نرم‌افزاری به یکدیگر، به خودیِ خود یکی از پرچالش‌ترین مسائل در طراحی نرم‌افزار است. در این بخش به بررسی مشکلاتی که ممکن است رخ دهد، می پردازیم:1- عدم تطابق خروجی یک ماژول نرم‌افزاری با ورودی ماژول بعدی در سیستمهای نرم‌افزاری، داده‌ها در بین بخش‌ها و ماژول‌های مختلف در جریان اند و به صورت مداوم از یک ماژول خارج و به ماژول دیگر وارد می‌شوند. در حین این گردش اطلاعات، ممکن است داده‌ای که از اینترفیس ورودی وارد ماژول می شود، گم شود یا اینکه جوری تغییر کند که در جریانِ داده‌ی برنامه  انتظار آن را نداشته‌ایم. در اینصورت،‌ استفاده از این داده، عملا برای ماژول های بعدی ناممکن می شود. (مثلا در یک کلاس،‌ انتظار داشته‌ایم که یک عدد را به‌عنوان تعداد محصولات دریافت کنیم تا محاسبات مورد نیاز را روی آن انجام دهیم؛‌ اما ورودی ارسال شده به این کلاس،‌ از نوع String یا یک عدد منفی باشد. در اینصورت، طبیعتا این کلاس نمی‌تواند محاسبات مورد انتظار را انجام دهد چون تعداد محصولات، به درستی به او گزارش نشده‌است.) 2- تاثیر مخرب یک بخش بر روی بخش دیگریک بخش از برنامه ممکن است وقتی به تنهایی کار می‌کند،‌ هیچ مشکلی ایجاد نکند؛‌ اما در هنگام اضافه شدن به سیستم، به طور ناخواسته، یک تاثیر مخرب روی ماژول‌های دیگر داشته باشد و کار آنها را مختل کند. در نتیجه عملکرد یک ماژول نرم‌افزاری، علاوه بر ویژگی‌ها و ساختار خود  ماژول، به عملکرد ماژول‌های دیگر نیز بستگی دارد و ماژول‌های متفاوت می توانند از یکدیگر تاثیر مخرب بگیرند.3- نتیجه‌ی کلی کار بخش‌های مختلف،‌ چیزی نباشد که ما انتظار داریمهر کدام از بخش‌های کوچکتر سیستم،‌ طبیعتا با توجه به تعریفی که دارند برای انجام یک عملیات کوچک طراحی شده اند. ما توقع داریم بعد از کنارهم گذاشتن این بخش‌های کوچک، بتوانیم یک کار بزرگ را انجام دهیم و پس از انجام آن، نتیجه ی درستی بگیریم. اما زمانیکه این بخش ها با هم شروع به همکاری می‌کنند، ممکن است نتوانند با کمک یکدیگر آن کاربرد کلی‌ای که ما از نتیجه‌ی کار آنها انتظار داریم را تولید کنند. در اینصورت باید معماری نرم‌افزار و روابط بین بخش‌ها بازنگری شوند تا خروجی همکاری این کلاسها،‌ مطابق چیزی که انتظار داریم تکمیل شود.4- اگر مشکل کوچکی در یک ماژول وجود داشته باشد،‌ با بزرگتر شدن سطح برنامه،‌ مشکل هم بزرگتر می‌شودفرض کنید درون یک ماژول نرم‌افزاری،‌ یک مشکل کوچکی جا مانده باشد که در مرحله‌ی Unit Test پیدا و رفع نشده است . طبیعتا با توجه به اینکه اندازه و پیچیدگی این ماژول جزئی،‌در مقایسه با کل سیستم کوچکتر و ساده تر است،‌ خطایابی و رفع خطا نیز آسانتر از زمانی است که این ماژول به‌عنوان جزئی از یک سیستم در نظر گرفته شده‌است. علاوه بر سادگی، ممکن است این مشکل وقتی وارد ماژول های بزرگتر برنامه می شود، بزرگتر و جدی‌تر هم بشود و روند برنامه را دچار مشکل کند! در صورتیکه شاید زمانیکه هنوز به سیستم اضافه نشده‌بود،‌ همچنین اثر مخربی روی روند اجرای کار ماژول نداشت.5- متغیرهای global به دلیل اینکه حوزه‌ی تعریفشان بزرگ است،‌ بیشتر ممکن است دچار مشکل شوندمتغیرهایی که به صورت global تعریف می شوند، بخاطر سطح دسترسی‌ای که از تمام بخش‌های کلاس دارند،‌ بیشتر ممکن است دچار چالش شوند. برای مثال ممکن است مقدار آنها درون هر تابع به صورت جداگانه تغییر کند. طبیعی‌است که اگر تحت شرایطی، یکی از توابع مقدار این متغیر را طوری تغییر دهد که در جریان برنامه تعریف نشده است،‌ مقدار آن غیر معتبر می‌شود و می‌تواند کل برنامه را دچار مشکل کند.6- و خیلی مشکلات دیگر که می تواند در هنگام ترکیب کردن ماژولهای کوچکتر رخ بدهد که تعداد آنها میتواند به اندازه‌ی تمام سیستمهای نرم‌افزاری دنیا و تمام دفعاتی که قرار است یک ماژول جدید به هرکدام از آنها اضافه شود، باشد...استراتژی های تست یکپارچگی روش بیگ بنگ (Big Bang)برای تست یکپارچگی سیستم نرم‌افزاری، دو رویکرد کلی وجود دارد. یکی اینکه تمام ماژول‌های کوچکتر را در یک مرحله و بدون هیچ ترتیب خاصی با هم ترکیب کنیم و بعد شروع به بررسی مشکلات پیش آمده و رفع خطاهای موجود بکنیم. به این روش، روش بیگ بنگ می گویند زیرا در این روش،‌ درست مثل واقعه ی بیگ بنگ، یکدفعه همه ی اجزای جهانِ سیستم نرم‌افزاری ما، باهم ترکیب می‌شوند و سپس خطاها و مشکلات موجود در سیستم رفع می‌شود. خب همانطور که احتمالا حدس می‌زنید؛‌ این روش، اصلا روش خوبی نیست. چون در این رویکرد، پیدا کردن عامل خطاها و تفکیک خطاهای مربوط به ماژول‌های مختلف بسیار سخت شده و متعاقبا رفع آن خطاها نیز به مراتب سختتر می شود.روش افزایشی در مقابل روش بیگ بنگ، یک رویکرد دیگر نیز برای تست یکپارچگی (Integration test) وجود دارد که در طی آن، تک‌تک ماژول‌ها را جداگانه تست کرده و از درست‌بودن آنها مطمئن می‌شویم. سپس طبق استراتژی انتخاب شده، یک ترتیب خاص برای تست یکپارچگی انتخاب می کنیم و در هرمرحله، تعدادی از ماژول‌ها را باهم ترکیب می کنیم تا زمانیکه کل سیستم آزمایش شود. ترتیب ترکیب این ماژول‌ها،‌ می‌تواند به‌صورت‌های زیر باشد:1- یکپارچگی از بالا به پایین (Top-Down Integration)در این روش، همانطور که از نام آن پیداست، ابتدا از ماژول‌های سطح بالاتر و کلی‌تر شروع می کنیم و ارتباطات و اینترفیس های آنان را تست می کنیم. سپس در هر مرحله، طی الگوریتمی به ماژول های سطح پایین‌تر می‌رویم و انقدر این مراحل را طی می‌کنیم که کل سیستم از نظر یکپارچگی بین کامپوننت ها تست شده باشد. یکپارچگی از بالا به پایین (Top-Down Integration)2- یکپارچگی از پایین به بالا (Bottom-Up Integration)در این روش، همانطور که از نام آن پیداست، عملیات تست کردن از کوچکترین ماژول‌ها که در پایین‌ترین سطوح دیاگرام ساختار برنامه هستند شروع می شود و در هرمرحله، با ادغام‌کردن کامپوننت‌های مختلف، برگ های نمودار را حذف کرده و نتیجه ی ادغام آنها را به عنوان برگ‌های کامپوننت‌های بالاتر در نظر می‌گیرد تا با آنها ترکیب شوند و یکپارچگی سیستم مورد آزمایش قرار بگیرد. یکپارچگی از پایین به بالا (Bottom-Up Integration)3- یکپارچگی مداوم (Continuous Integration)در این روش، عملیات ادغام کامپوننت ها و تست آنها، تنها یکبار در انتهای توسعه‌ی نرم‌افزار انجام نمی‌شود! بلکه هر روز یا هر چند روز یکبار، تست یکپارچگی انجام می شود. این روش، برای گروههایی که مبنای فعالیتشان مدل توسعه ی چابک است؛ بسیار مفید می باشد. چراکه این گروهها باید هر چند وقت یکبار (که این زمان براساس سیاست کاری هر گروه می تواند متغیر باشد اما به هرحال معمولا زمان خیلی زیادی نیست) یک خروجی قابل انتشار از نرم‌افزار خود ارائه دهند و قاعدتا قبل از انتشار، باید تمام تست‌های لازم را روی آن انجام داده باشند و از پایدار بودن و قابل اطمینان بودن محصولی که منتشر کرده اند، مطمئن باشند یکپارچگی مداوم (Continuous Integration)Source : Roger S. Pressman, Bruce R. Maxim. &quot;Software Engineering A Practtitioner&#x27;s Approach&quot; - 9th Editionامیدوارم این سری از مقالات برای‌شما مفید بوده باشد.ممنون از همراهی شما</description>
                <category>محدثه سالم</category>
                <author>محدثه سالم</author>
                <pubDate>Mon, 30 May 2022 13:43:23 +0430</pubDate>
            </item>
                    <item>
                <title>تست برنامه‌های مبتنی بر شیءگرایی</title>
                <link>https://virgool.io/fboard/%D8%AA%D8%B3%D8%AA-%D8%A8%D8%B1%D9%86%D8%A7%D9%85%D9%87-%D9%87%D8%A7%DB%8C-%D9%85%D8%A8%D8%AA%D9%86%DB%8C-%D8%A8%D8%B1-%D8%B4%DB%8C%D8%A1%DA%AF%D8%B1%D8%A7%DB%8C%DB%8C-nxwkvfnukezx</link>
                <description> در مقاله‌ی قبل،‌ دو تا از مهمترین و جالبترین استراتژی‌های تست نرم‌افزار یعنی استراتژی‌های تست جعبه سفید و تست جعبه سیاه را معرفی کردیم. همانطور که گفتیم؛ این استراتژی‌ها معمولا ماژول‌های نرم‌افزاری را به‌صورت کلی بررسی می‌کنند. اما بعضی مواقع،‌ موقعیت‌هایی پیش می‌آید که در آنها می‌خواهیم مطمئن شویم که در یک کلاس،‌ روند اجرای برنامه حتما یک ترتیب خاصی را رعایت می‌کند و هیچ‌وقت این ترتیب به‌هم نمی‌ریزد. این موقعیت‌ها،‌ معمولا در برنامه‌های مبتنی بر شی‌ءگرایی ایجاد می‌شوند و در این مقاله می‌خواهیم درباره‌ی استراتژی تست نرم‌افزار در این موقعیت‌ها، صحبت کنیم. در ادامه با من همراه باشید.وی‍ژگی خاص برنامه‌های شیءگرا که عملیات تست را پیچیده می کندویژگی بارز برنامه‌های مبتنی بر شی‌ءگرایی این است که این برنامه‌ها معمولا از کلاس‌ها و ماژول‌های نرم‌افزاری مختلفی در کنارهم استفاده می‌کنند؛ در نتیجه در هنگام اجرای جریان کنترل برنامه،‌ مجبورند بارها و بارها بین خط‌های مختلف این کلاسها در رفت و آمد باشند و این موضوع باعث پیچیده شدن جریان اجرای برنامه می‌شود. از طرفی،‌در برنامه‌های شیءگرا، ما طبیعتا میتوانیم با ساختن آبجکت از یک کلاس،‌ از توابع درون کلاس استفاده کنیم. اما ممکن است منطق و مفهوم برنامه جوری چیده‌شده‌باشد که از نظر مفهومی اجازه نداشته باشیم تابعی را قبل از صدا زدن تابع دیگری استفاده کنیم. به هر حال ما به‌عنوان تست کننده‌ی این کلاسها،‌ باید مطمئن باشیم در این رفت‌وآمدها و پرش‌های کد،‌ ترتیب اجرای دستورات به درستی انجام می‌شود و جریان اجرای برنامه در اواسط راه گم نمی‌شود‍! از طرفی همانطور که گفتیم، در بعضی از کلاسها به دلیل الزاماتی که از نظر مفهومی وجود دارد،‌ ممکن است ما بخواهیم توابع و عملیات ها،‌ حتما طبق یک ترتیب خاص و مشخصی اجرا شوند. و از آنجاییکه در تست،‌ می‌خواهیم از برآورده شدن الزامات مطمئن شویم،‌ باید برای کنترل این موارد از استراتژی‌های تست کمک بگیریم.مفهوم دقیق یک Unit نرم‌افزاری در Unit Test چیست؟همانطور که در مقاله‌های قبل گفتیم؛ در Unit Test،‌ منظور ما از یک یونیت لزوما یک متد یا یک کلاس نیست! بلکه در هر بخش از برنامه،‌ مفهوم یونیت میتواند به طور مجزا تعریف شود. یکی از مفاهیمی که باعث متفاوت شدن مفهوم یک یونیت در برنامه‌نویسی شیءگرا شده‌است،‌ مفهوم encapsulation است. با استفاده از این مفهوم، در کنار کلاسی که عملیات‌ها را انجام می‌دهد،‌ یک کلاس دیگر نیز داریم که متغیرها را در خود نگه میدارد و به کمک توابع getter و setter،‌ می‌تواند به ما اجازه بدهد که مقدار متغیرها را بخوانیم و یا آن را تغییر دهیم. در این مقاله درباره‌ی اینکه چرا این کار را می‌کنیم و چطور آن را پیاده‌سازی می‌کنیم،‌ صحبت نمی‌کنیم چرا که هدف از این مقاله‌، بررسی نحوه‌ی تست‌کردن این کلاس‌ها است اما نکته‌ای که وجود دارد این است که با توجه به مطالب گفته‌شده، ما نمی‌توانیم این دو کلاس را به صورت مجزا تست‌کنیم چون بدون حضور یکدیگر عملکرد کاملی ندارند. در نتیجه مجموعه‌ی این کلاسها را یک یونیت در نظر می‌گیریم و آنها را در کنار هم مورد آزمایش قرار می‌دهیم.نمای کلی از Encapsulationدر واقع در Unit test، ما کلاسی که در حال اجرا است را به همراه Model ها و همچنین Controller ها یا Adapter های مربوطه که فرآیندهای مختلفی برای شروع به کار آن کلاس انجام میدهند را یک یونیت در نظر میگیریم تا بتوانیم رفتار کلی آن بخش را تست کنیم. البته این یونیت ها کوچکترین مفاهیمی که قابل تست کردن هستند نیستند و ما میتوانیم برای تک تک متد های درون برنامه تست بنویسیم. این کار زمانی بیشتر اهمیت پیدا می کند که بخواهیم متدهایی که در کلاس وجود دارند و از قسمتهای مختلف برنامه مورد استفاده قرار می گیرند را تست کنیم و یا در جریان روند برنامه و تحلیل رفتار آن، نیاز باشد که حتما یک روند خاصی در کنار الگوهای اختیاری دیگر وجود داشته باشد. برای مثال اگر بخواهیم کلاس مدیریت اکانت بانکی را بسازیم،‌ قاعدتا باید متدهایی مثل بازکردن حساب،‌بستن حساب،‌برداشت از حساب،‌ واریز به حساب و... داشته باشیم. با استفاده از این متدها و ترکیب‌های مختلف استفاده از آنها،‌ قاعدتا میتوانیم فرآیندهای مختلفی را طی کنیم. اما در هرحال، باید برای هرکاربر حتما ابتدا حساب بازکنیم و در نهایت هم باید دسترسی به حساب را ببندیم. و نمیتوانیم حتی ترتیب اینها را جابجا کنیم!‌ در این شرایط تست ها به کمک ما می‌آیند تا بتوانیم رفتار برنامه را شبیه سازی کنیم.در شکل زیر،‌ نمونه‌ای از testcase هایی که می‌توانیم برای کلاس مدیریت حساب‌های بانکی بنویسیم آورده شده‌است:چند نمونه از TestCaseهای کلاس مدیریت حساب‌های بانکیهمانطور که در خط اول دیده می‌شود،‌ از نظر عملکرد مفهومی یک حساب بانکی، حداقل عملیات‌هایی که باید &quot;به‌ترتیب&quot; اتفاق بیفتد،‌شامل بازکردن حساب، واردکردن مشخصات حساب،‌ سپرده‌گذاری، برداشت از حساب و در نهایت بستن حساب است. قطعا اگر قبل از اینکه حساب بازشود قصد داشته‌باشیم از آن برداشت کنیم،‌ مفهومی ندارد و قابل اجرا نیست! البته که عملیات‌های زیاد دیگری نیز ممکن است در بازه‌ی باز شدن حساب تا بستن آن پیش بیاید و محدودیتی در این باره وجود ندارد. تنها محدودیتی که هست این است که تمام عملیات‌های اساسی که در اولین فرآیند درون شکل آمده است،‌ حتما با ترتیب مشخص شده‌ اجرا شوند. TestCaseهای r1 و r2،‌ دو نمونه از فرآیندهای احتمالی دیگر را نشان می‌دهند.یک نقشه‌ی کلی از برنامه برای کمک به بهتر مشخص شدن TestCaseهاتست برنامه زمانی کامل می شود که تست نوشته شده،‌ تمامی حالاتی که ممکن است در روند برنامه نوشته شده رخ دهد را حداقل یکبار طی کرده باشد. کشیدن State Diagram یا دیاگرام حالت در این مسیر خیلی می‌تواند به ما کمک کند. به کمک این دیاگرام،‌ ‌حالت‌های مختلف اجرای نرم‌افزار را متوجه می شویم تا بتوانیم با دقت بیشتری برای آن تست طراحی کنیم. حال اگر کلاسی که میخواهیم بررسی کنیم، با کلاس های دیگری نیز همکاری می کند و درارتباط است، تعداد این دیاگرام های حالت بیشتر از یکی می شود و باید تمام آنها را در کنار هم بررسی کنیم تا جریان رفتاری نرم‌افزار را متوجه شویم و تمام حالات ممکن را در نظر بگیریم. در شکل زیر،‌ State Diagram مربوط به کلاس مدیریت حساب بانکی برای نمونه آورده‌شده است. با دنبال کردن جریان فرآیندها در این دیاگرام،‌ می‌توانیم تمام فرآیندهایی که این کلاس ممکن است طی کند را رصد کنیم.دیاگرام حالت مربوط به برنامه‌ی مدیریت حساب‌های بانکیSource : Roger S. Pressman, Bruce R. Maxim. &quot;Software Engineering A Practtitioner&#x27;s Approach&quot; - 9th Editionدر مقاله‌ی بعدی، درباره‌ی تست یکپارچگی یا Integration Testing صحبت می‌کنیم. با توجه به اینکه Integration Test مربوط به یکپارچگی تک‌تک اعضای سیستم در کنار هم و تعامل آنها با یکدیگر می‌باشد، شامل مباحث جذابی می‌شود. از همین‌جا از شما دعوت می‌کنم مقاله‌ی بعدی را نیز مطالعه کنید.امیدوارم مقالات برای‌شما مفید بوده باشد. ممنون از همراهی شما</description>
                <category>محدثه سالم</category>
                <author>محدثه سالم</author>
                <pubDate>Mon, 13 Dec 2021 00:03:52 +0330</pubDate>
            </item>
                    <item>
                <title>استراتژی تست جعبه‌ سفید و تست جعبه‌ سیاه</title>
                <link>https://virgool.io/@mohsal110/%D8%A7%D8%B3%D8%AA%D8%B1%D8%A7%D8%AA%DA%98%DB%8C-%D8%AA%D8%B3%D8%AA-%D8%AC%D8%B9%D8%A8%D9%87-%D8%B3%D9%81%DB%8C%D8%AF-%D9%88-%D8%AA%D8%B3%D8%AA-%D8%AC%D8%B9%D8%A8%D9%87-%D8%B3%DB%8C%D8%A7%D9%87-f5wnw2pakjun</link>
                <description>در این مقاله،‌ می‌خواهیم چند استراتژی مهم برای تست نرم‌افزار را معرفی کنیم. این استراتژی‌ها به ما کمک می‌کنند اهداف تست را به صورت عملی محقق کنیم و شامل سه استراتژی جعبه‌ سفید،‌ جعبه‌ سیاه و همچنین تست نرم‌افزار بر مبنای شیءگرایی می‌باشد. البته برای اینکه مقاله خیلی طولانی و کسل‌کننده نشود؛‌ در این مقاله،‌ تنها دو استراتژی اول را معرفی می‌کنیم و در مقاله‌ی بعدی به استراتژی سوم می‌پردازیم.تست جعبه سفید چیست؟تست جعبه سفید (White-Box Testing) که با نام‌های دیگری مثل تست ساختاری (Structural Testing) یا تست جعبه‌ی شیشه‌ای (Glass-Box Testing) نیز شناخته می‌شود؛ بر این اساس طراحی شده است که انگار ماژول نرم‌افزاری مورد بررسی را درون یک جعبه‌ی شیشه‌ای قرار داده‌ایم و از بیرونِ دیواره‌های شفاف آن،‌ با دقت به جزئیات عملکرد هر بخش نگاه می‌کنیم و درستیِ عملکرد آنها را چک می‌کنیم تا از این بابت اطمینان پیدا کنیم که تمام مسیرهای ممکن برای اجرای برنامه، حداقل یکبار به‌درستی کامپایل و اجرا می‌شوند و دستوری وجود ندارد که درون کدها پیش‌بینی شده باشد اما از طریق جریان اجرای برنامه،‌ به هیچ طریقی نتوانیم به آن دسترسی پیدا کنیم. (در مقاله‌ی قبل مفصل در این‌باره صحبت کردیم. از شما دعوت می‌کنم برای بررسی بهتر، روی لینک ارائه شده کلیک کنید.)اهداف روش جعبه سفیدکلمه‌ی کلیدی استراتژی جعبه سفید،‌ &quot;اطمینان&quot; است! ما تست جعبه سفید را انجام می‌دهیم تا از نبود مشکل در ماژول نرم‌افزاریمان &quot;اطمینان&quot; حاصل کنیم. در این قسمت،‌ بخش‌های مختلفی که می‌توانیم به کمک این استراتژی،‌ از درست بودن عملکردشان اطمینان پیدا کنیم را معرفی می‌کنیم:-  تمام مسیر های مستقلی که یک ماژول از برنامه می‌تواند طی کند را حداقل یک بار امتحان کرده و تضمین کنیم که تمام این مسیرها، می‌توانند بدون هیچگونه مشکلی اجرا شوند.-  در ساختارهای شرطی و انشعابی مثل if و switch ،‌ مطمئن باشیم که تمام دستوراتی که درصورت وقوع حالتهای مختلف متغیر شرط نوشته شده‌اند؛‌ حداقل یک بار اجرا می‌شوند (یعنی دستوری وجود ندارد که تحت هیچ حالتی قابل اجرا نباشد) و از آن مهم‌تر اینکه دستورات اجرا شده درست و بدون مشکل اجرا می‌شوند.-  تمام حلقه‌های موجود در برنامه را درون مقادیر مرزی و نزدیک به مرز شرط حلقه‌ها تست کنیم تا مطمئن‌شویم که در آن مقادیر، به هیچ مشکلی برنخواهندخورد.-  تمام ساختمان‌داده‌های درونی برنامه را اعتبارسنجی کنیم تا از معتبر بود آنها اطمینان پیدا کنیم.تکنیک‌های اساسی استراتژی تست جعبه سفیدروش تست جعبه سفید،‌ به طور کلی سه تکنیک اصلی دارد:پوشش‌دهی دستورات (Statement Coverage)در این تکنیک، منظور از statement همان خط‌های کد می‌باشد. این تکنیک مشخص می کند که آیا تمام خط‌های کد،‌ حداقل یکبار به‌درستی کامپایل و اجرا می شوند یا خیر؟!نمونه ای از تحلیل Statement Coverage توسط JUnit در محیط intelliJپوشش‌دهی شاخه‌ها (Branch Coverage)در اینجا،‌ منظور از branch،‌ جایی از کد برنامه است که در آن، ساختار if و یا ساختار های شبیه به آن (مانند switch) وجود داشته باشد. همانطور که می‌دانید، در این بخش‌ها برنامه باید بسته به حالتی که متغیر شرطی آن دارد؛‌ به شاخه‌های مختلف تقسیم شود. این تکنیک وظیفه دارد که مشخص کند که آیا تمامی شاخه‌های برنامه (که برای if دو شاخه و برای switch‌چندین شاخه است) بسته به نیاز برنامه به درستی انجام می‌شود یا خیر؟!نمونه‌ای از خروجی HTML حاصل از اجرای Branch Coverage توسط JUnit در محیط intelliJ پوشش‌دهی مسیرها (Path Coverage) این تکنیک،‌ یک تکنیک جامع است که مشابه branch coverage اما قوی‌تر از آن بوده و برای آزمایش برنامه‌های پیچیده مفید است. در این تکنیک، هدف این است که مطمئن شویم تمام مسیرهای برنامه حداقل یکبار به‌درستی پیموده شده است. با توجه به هدف تکنیک پوشش‌دهی مسیرها،‌ طبیعی است که پردازش آن به مراتب سختتر از موارد دیگر هم باشد.تفاوت تئوری و عملکرد تست جعبه سفید در دنیای واقعیهمانطور که در بخش اهداف تست جعبه سفید گفتیم؛ در این استراتژی، هدف این است که به &quot;اطمینان&quot; برسیم از اینکه برنامه‌ی مورد بررسی‌مان درست کار می‌کند. و در دنیای کامپیوتر و احتمالات،‌ چه چیزی بهتر است از اینکه مطمئن شویم نرم‌افزارمان کاملا درست کار میکند؟! طبیعتا هیچ چیز. درست است که اگر تست جعبه سفید،‌ کاملا انجام شود و تمام مسیرهای اجرای برنامه کاملا چک شود؛‌ اتفاق خیلی خوبی می‌افتد. اما واقعیت این است که در دنیای واقعی،‌ تعداد راههای ممکن برای اجرای برنامه بسیار زیاد هستند و هرکدام از آنها،‌ طبیعتا نیازمند حجم زیادی از پردازش‌ها هستند. به همین دلیل،‌ عملا برای خیلی از سیستم‌های نرم‌افزاری،‌ نمی‌توانیم استراتژی جعبه سفید را به صورت کامل پیاده سازی کنیم! تنها راهی که برای تست کردن همچنین نرم‌افزارهایی داریم،‌ این است که بسته به نوع پروژه و ویژگی‌های حساس ماژول‌های آن،‌ تعداد معقولی از مسیرهای منطقیِ مهم را برای تست‌کردن انتخاب کنیم و تست جعبه سفید را تنها و تنها برای همین مسیرهای انتخاب شده اجرا کنیم. (در مقاله‌ی قبل درباره‌ی نقاط آسیب‌پذیر هر ماژول،‌ به‌طور مفصل صحبت کردیم)تست جعبه سیاه چیست؟بعد از اینکه از دیواره‌های شیشه‌ای جعبه‌‌ی سفید،‌ با دقت به ساختار درونی ماژول‌های مختلف نگاه کردیم و از درست‌بودن عملکرد آنها مطمئن شدیم؛ حالا وقت آن است که دیواره‌های شیشه‌ای جعبه را با رنگ سیاه،‌ کاملا بپوشانیم تا دیگر به ساختار درونی آن توجهی نکنیم. در این تست،‌ هدف این است که مطمئن شویم ماژول نرم‌افزاری ای که بعد از انجام تست جعبه‌ی سفید،‌ اطمینان داریم که حتما درست کار می‌کند؛ می‌تواند با ماژول‌های دیگرِ سیستم‌ نرم‌افزاریمان نیز به خوبی تعامل کند و با کمک یکدیگر خروجی‌ای که از آنها انتظار می‌رود را تولید کنند. در این روش، ما به هیچ وجه نمیخواهیم ساختار درونی ماژول را درنظر بگیریم و تنها تمرکز خود را روی ورودی‌ها و خروجی‌های سیستم نرم‌افزاری قرار می‌دهیم. این استراتژی،‌ با نام‌های تست رفتاری (Behavioral Testing) یا تست عملکردی (Functional Testing) نیز شناخته می‌شود.تست جعبه‌ی سیاه، یک جایگزین برای تست جعبه سفید نیست! بلکه مکمل آن است. این استراتژی،‌ وظیفه دارد انواع دیگری از خطاها را کشف کند که تست جعبه سفید نمیتواند آنها را کشف کند. تست جعبه سیاه چه زمانی باید انجام شود؟برای پاسخ به این سوال،‌ باید بگوییم که بهتر است تست جعبه سیاه را هم قبل از توسعه‌ی نرم‌افزار و هم بعد از آن انجام دهیم. چرا که در هرکدام،‌ می‌توانیم اهداف و رویکردهای متفاوتی را دنبال کنیم که می‌توانند به اعتبارسنجی برنامه‌ی ما کمک کند.برای نوشتن تست جعبه سیاه،‌ لزوما نیازی نیست تا کامل شدن فرآیند توسعه‌ی نرم‌افزار صبر کنیم. بلکه تنها زمانی که نوع و ترتیب داده‌های ورودی و خروجی ماژول و نحوه‌ی ارتباط ماژول های مختلف (که توسط معمار نرم‌افزار طراحی می‌شوند) مشخص شد، مسئول تست میتواند تست های مربوط به این سطح را بنویسد و حتی به کمک آنها مشخص کند که در هر مرحله باید چه ورودی هایی وارد هر ماژول شود تا همه ی نیازها را پوشش دهند. همچنین می‌توانیم مشخص کنیم که انتظار داریم از هر ماژول،‌ چه خروجی‌هایی دریافت کنیم که با ماژول های بعدی و کل سیستم نرم‌افزاری یکپارچه شود. این کار، حتی به توسعه ی بهتر نرم‌افزار نیز کمک می‌کند.علاوه بر آن،‌ لازم است بعد از توسعه‌ی سیستم نرم‌افزاری نیز تست جعبه سیاه انجام شود. چراکه در این تست، تمرکز بر روی ساختار برنامه و پیاده سازی آن نیست! بلکه تمرکز بر روی اطلاعات ورودی و خروجی سیستم می‌باشد که بعد از تکمیل توسعه نرم افزار تولید می شود. در نتیجه باید مطمئن باشیم که بعد از توسعه‌ی سیستم نرم‌افزاری،‌ جریان اطلاعات درون برنامه به درستی شکل گرفته است و ماژول‌های مختلف برنامه میتوانند به خوبی باهم کار کنند و نتیجه‌ی درستی تولید کنند.چه خطاهایی توسط تست جعبه سیاه کشف می‌شوند؟خطاهایی که توسط تست جعبه سیاه شناخته می‌شوند،‌ شامل موارد زیر می‌باشند:-  بخشی از نرم‌افزار عملکرد نادرست دارد و یا بخشی از عملیات‌هایی که می خواهیم انجام دهد را انجام نمی‌دهد. (درصورتیکه داده‌های خروجی تولید شده از یک ماژول،‌ صحیح نباشد)-  مشکل در interface ها. منظور از interface ورودی‌ها و خروجی‌های بخش‌های مختلف برنامه است.-  مشکل در ساختمان‌داده های استفاده شده برای ورودی‌ها و خروجی‌ها و یا مشکل در دسترسی به دیتابیس خارجی-  خطاهای مربوط به رفتار یا بازدهی سیستم-  خطاهای مربوط به مقداردهی‌های اولیه و تنظیمات مورد نیاز برای شروع‌شدن اجرای نرم‌افزار و یا خطاهای مربوط به پایان یافتن اجرای برنامهانواع روش‌های تست جعبه سیاهتست جعبه سیاه،‌ دارای تکنیک‌ها و راههای مختلفی است که در این بخش،‌ آنها را بررسی می‌کنیم:تست ورودی‌ها و خروجی‌ها (Interface Testing)در اکثر برنامه ها، کامپوننت‌های مختلف جوری طراحی می‌شوند که باید وابسته به هم کار انجام دهند و به تنهایی کاربرد خاصی ندارند. به همین دلیل این موضوع خیلی مهم است که مطمئن شویم این کامپوننت‌های مجزا از هم، زبان یکدیگر را می فهمند و اصطلاحا با همدیگر یکپارچه هستند. به این صورت که اگر قرار باشد داده‌ای به یک کامپوننت نرم‌افزاری برسد، با ترتیب و نوع داده ای باشد که در تعریف ورودی‌های خود انتظار آمدنش را داشته است و خودِ این کامپوننت هم خروجی‌ای تولید کند که از نظر ترتیب و نوع داده، طوری باشد که مراحل بعدی برنامه از او میخواهند. تا کامپوننت های بعدی نیز بتوانند از نتیجه ی این بخش برای انجام کارهای بعدی استفاده کنند. این تست در واقع جزء مراحل Integration Test محسوب میشود. البته با توجه به اهمیت این یکپارچگی خروجی‌ها و ورودی‌ها، خیلی از توسعه‌دهنده‌ها نیاز می‌دانند که در حین توسعه نیز، با اضافه کردن کدهای اضافی تا حدی که امکان دارد  آنها را چک کنند و برای بررسی صحت آنها، منتظرِ به پایان رسیدن برنامه نمانند.نحوه‌ی نگرش ما به سیستم نرم‌افزاری در هنگام بررسی ورودی و خروجی‌ها ( interfaceها )دسته‌بندی هم‌ارزها (Equivalence Partitioning)دسته بندی هم‌ارزها، یکی از روش های تست جعبه سیاه است که  در آن، ورودی ها را به دسته های مختلفی تقسیم می کنیم به طوریکه هر دسته، بتواند یکی از حالتهای Test case را نشان بدهد. یک Test case ایده آل، باید جوری طراحی شده باشد که بتواند به تنهایی یک دسته از خطاها را آشکارکند. (مثلا همه ی جاهایی که کاراکترهای اطلاعات، اشتباه پردازش شده اند) در غیراینصورت (اگر Test case ها اینطور طراحی نشوند)، ممکن است قبل از اینکه تست مربوطه اجرا شده و خطاها شناخته شود؛ در جاهای دیگرِ برنامه این فرآیند اجرا شده باشد و به این ترتیب خروجی‌های اشتباهی تولید شده و در جریان برنامه قرار بگیرند که هیچوقت شناسایی نمی‌شوند.نحوه‌ی دسته بندی گروههای هم‌ارزهر Test case طراحی شده برای این روش، براساس سنجش کلاس های هم‌ارزی برمبنای شرطِ ورودی تعیین می‌شود. به این ترتیب، اگر یک مجموعه‌ای از اشیاء با هم رابطه‌ی تقارنی، تعدی و ترایایی داشته باشد؛ براساس قوانین مجموعه‌ها، آن مجموعه دارای رابطه‌ی هم ارزی است و اعضای آن با یکدیگر هم‌ارز هستند. یک کلاس هم‌ارزی، نشان دهنده‌ی مجموعه‌ای از شرط‌های ورودی معتبر و غیرمعتبر می‌باشد که میتواند شامل یک عدد یا یک رنجی از اعداد و یا مجموعه ای از مقادیر مرتبط با هم یا حتی یک شرط بولین باشد. البته Test case ها به گونه ای انتخاب می‌شوند که بیشترین تعداد صفات از یک کلاس هم‌ارزی به طور همزمان اعمال شود. این کار باعث میشود که تعداد Test case ها تا حد امکان کاهش پیدا کند و تعداد فرآیند های تستی که باید ایجاد شود، به مراتب کمتر شده ودر نتیجه، بار محاسباتی پردازش تست نیز به‌شدت کاهش پیدا کند. چرا که نوشتن تست برای تمام حالات ممکن، حتی برای یک برنامه‌ی حلقه‌ی ساده با شرط محدود هم به شدت سنگین خواهد شد و خیلی زود ممکن است از توان سخت‌افزارهای در دسترس ما خارج شود. بعد از تعریف‌شدن کلاسهای هم ارزی، حالت های زیر ممکن است برای Test caseهای ما ایجاد شود. با استفاده از این دستورالعمل و کلاس بندی، میتوانیم به راحتی داده‌ها را تقسیم بندی کرده و پردازش کنیم:1. اگر شرط ورودی، محدوده‌ای را مشخص کند؛ یک کلاسِ معادلِ معتبر و دو کلاسِ معادلِ نامعتبر تعریف می‌شود. چرا که باید قبل از آن محدوده و بعد از آن را به عنوان کلاسهای نامعتبر در نظر بگیریم.2. اگر شرط ورودی به مقدار خاصی نیاز داشته باشد؛ یک کلاسِ معادلِ معتبر و دو کلاسِ معادلِ نامعتبر تعریف می شود. چرا که باید قبل از آن مقدار وبعد از آن را به عنوان کلاسهای نامعتبر در نظر بگیریم.3. اگر شرط ورودی یک عضو از یک مجموعه را مشخص کند؛ یک کلاسِ معادلِ معتبر و یک کلاسِ معادلِ نامعتبر تعریف می شود. چون این عضو مشخص، یا در مجموعه وجود دارد و یا وجود ندارد!4- اگر شرط ورودی بولین باشد، یک کلاسِ معتبر و یک کلاسِ نامعتبر تعریف می شود. چون این شرط یا درست است و یا غلط و به هرحال در یکی از این دو مجموعه قرار می‌گیرد.نمونه‌ای از کلاسهای هم‌ارزی ایجاد شده برای یک مسئله‌ی کوچکارزیابی متغیرهای مرزی (Boundary Value Analysis) همانطور که قبلا هم اشاره کردیم؛ تعداد قابل توجهی از خطاهایی که ممکن است در برنامه رخ دهد، زمانی رخ می‌دهد که نرم‌افزار می‌خواهد ورودی‌هایی را پردازش کند که در مرزهای رنج کلاس‌های هم‌ارزی قرار دارند. نه در مرکز رنج. به همین دلیل است که در تست نرم افزار، یک تکنیک مجزا به نام تجزیه و تحلیل مقادیر مرزی یا Boundary Value Analysis ایجاد شده است. این تکنیک، در واقع مکمل تکنیک قبلی یعنی تکنیک دسته‌بندی هم‌ارزها است که در آن، به جای آنکه روی تمام مقادیر، عملیات تست را انجام دهیم؛ بعد از کلاس‌بندی اعضای هم‌ارز، تنها مقادیر مرزی را چک می کنیم تا از نبودن خطا برای این ورودی ها مطمئن شویم.البته که اکثر برنامه‌نویس‌ها، برای کاهش احتمال وجود خطا، درهنگام توسعه نیز این تست‌ها را انجام می دهند. بعد از اینکه مقادیر مرزی را به‌صورت جداگانه حساب کردیم، مقادیر خروجی متناظر با این ورودی‌های خاص نیز به‌طور خودکار محاسبه می شوند و به این ترتیب BVA میتواند به رنج‌بندی‌ شدن خروجی‌های Test case ما نیز کمک کند.دستورالعمل‌های BVA از بسیاری از جهات مشابه دستورالعمل‌های تکنیک دسته‌بندی هم‌ارزهاست:1- اگر شرط ورودی، یک رنج محدودی از اعداد (از aتاb) را مشخص کند؛ Test case ها باید با مقادیر a و b و یک واحد پایین تر از a و یک واحد بالاتر از b آزمایش شوند.2- اگر شرط ورودی، تعدادی از مقادیر گسسته را مشخص کند؛ Test case ها باید با کمترین و بیشترین مقدار از میان آن مقادیر و یک واحد پایین تر از کوچکترین مقدار و یک واحد بالاتر از بزرگترین مقدار آزمایش شوند.3- دستورالعمل 1و 2 باید برای خروجی‌ها هم اعمال شوند. برای مثال اگر برنامه‌ای داشته‌باشیم که دما را به عنوان ورودی می‌گیرد و فشار را به ما می‌دهد؛ باید مطمئن باشیم که Test case های طراحی‌شده، گزارشی را به عنوان خروجی ایجاد کند که حداکثر (و حداقل) تعداد ورودی جدولِ مجاز را تولید کند.4- اگر درون برنامه، ساختمان‌داده‌ای مشخص‌ شده‌ بود که توسط توسعه‌دهنده، مرزهای محدودکننده‌ای برای آن تعریف شده بود، (به عنوان مثال ، یک آرایه که دارای 100 ورودی مشخص باشد) ، باید مطمئن شویم که Testcaseهای طراحی شده، مرزهای مشخص شده برای آن ساختمان‌داده را نیز پوشش می دهند.یک مثال ساده برای ارزیابی متغیرهای‌ مرزیSource : Roger S. Pressman, Bruce R. Maxim. &quot;Software Engineering A Practtitioner&#x27;s Approach&quot; - 9th Editionدرمقاله ی بعدی،‌ درباره‌ی سومین استراتژی مهم تست نرم‌افزار که مخصوص تست‌کردن برنامه‌هایی است که طبق اصول شیءگرایی توسعه‌داده شده‌اند، صحبت می‌کنیم. از آنجا که مقاله‌ی بعدی، به نوعی ادامه‌ی مطالب گفته شده در این مقاله است؛ از شما دعوت می‌کنم آن مقاله را نیز حتما مطالعه کنید.</description>
                <category>محدثه سالم</category>
                <author>محدثه سالم</author>
                <pubDate>Mon, 29 Nov 2021 18:49:56 +0330</pubDate>
            </item>
                    <item>
                <title>نقاط استراتژیکی که Unit Test باید بر روی آن نظارت کند!</title>
                <link>https://virgool.io/CE-SHAHED-publication/%D9%86%D9%82%D8%A7%D8%B7-%D8%A7%D8%B3%D8%AA%D8%B1%D8%A7%D8%AA%DA%98%DB%8C%DA%A9%DB%8C-%DA%A9%D9%87-unit-test-%D8%A8%D8%A7%DB%8C%D8%AF-%D8%A8%D8%B1-%D8%B1%D9%88%DB%8C-%D8%A2%D9%86-%D9%86%D8%B8%D8%A7%D8%B1%D8%AA-%DA%A9%D9%86%D8%AF-cmdmdw1lbl4o</link>
                <description>در مقاله‌ی قبل،‌ درباره‌ی سطوح مختلف تست نرم‌افزار صحبت کردیم و گفتیم فرآیند تست نرم‌افزار شامل تست اجزاء (Unit Test)،‌ تست یکپارچگی (Integration Test)،‌ تست اعتبار سنجی(Validation Test) و در نهایت تست کلی سیستمی(System Test) می‌شود. fا توجه به مطالبی که تا اینجا گفته‌شده است؛ هرکدام از این مراحل،‌ برای شناخت انواع متفاوتی از خطاها که مربوط به جنبه‌های مختلف نرم‌افزار می‌شود، طراحی شده‌اند. در این مقاله و مقاله‌های بعدی،‌ میخواهیم مشخص کنیم که در هنگام پیاده‌سازی هر مرحله، بیشتر باید روی چه بخش‌هایی از برنامه تمرکز کنیم و به دنبال چه نوع خطاهایی باشیم؟ برای این کار، ابتدا با اولین مرحله‌ی تست نرم‌افزار یعنی Unit Test شروع می‌کنیم که به بررسی عملکرد ساختار داخلی برنامه مربوط می‌شود.شکل کلی مواردی که باید در Unit Test بررسی شود.برای اینکه از عملکرد بخش‌های مختلف نرم‌افزار مطمئن شویم،‌ نیاز است آنها را مورد آزمایش قرار دهیم. اما برای آنکه بدانیم Unit موردنظر ما دقیقا باید از چه جهاتی مورد آزمایش قرار بگیرد و از آن سربلند بیرون بیاید تا بتوانیم بگوییم عملکرد آن قابل قبول است؛ باید بدانیم که در چه قسمتهایی از یک برنامه،‌ احتمال ایجاد خطا بیشتر است و اگر این بخش‌ها درست کار کنند،‌ با احتمال زیادی می‌توانیم بگوییم که Unit مورد نظر،‌ درست کار می‌کند. این بخش‌ها،‌ در تمام زبان‌های برنامه‌نویسی وجود دارند و تنها ممکن است نحوه‌ی پیاده‌سازی آنها متفاوت باشد پس مستقل از اینکه شما در حال استفاده از چه زبان برنامه‌نویسی ای هستید،‌ میتواند کمک کننده باشد. بعد از تمام این توضیحات،‌ وقت آن است که موقعیت‌های استراتژیک تست نرم‌افزار را معرفی  کنیم:آیا جریان اطلاعاتی که وارد ماژول شده و از آن خارج می شود درست و معتبر هستند؟اگر داده هایی که به ماژول نرم‌افزاری مورد نظر وارد می شوند، درست نباشد،‌ قاعدتا هیچ‌وقت نمیتوان متوجه شد که ماژول درست کار می کند یا خیر؟! چراکه حتی اگر ماژولِ در حال تست،‌ کاملا درست و بدون هیچ مشکلی کار کند هم ، مجددا خروجی‌های اشتباهی تولید می‌کند که ممکن است ما را درباره‌‌ی عملکرد بخش مورد نظر به اشتباه بیاندازد. پس زمانیکه متوجه می‌شویم جریان اطلاعات وارد شده بر یک ماژول ( چه از نظر نوع داده،‌ چه از نظر ترتیب داده‌ها و چه از نظر مقادیر آنها) با همان فرمتی که در متن برنامه پیش‌بینی و تعریف شده اند،‌ مطابقت ندارد؛‌ تا زمان رفع مشکل مراحل تست را متوقف می‌کنیم چرا که میدانیم تا زمان حل شدن مشکل،‌ درستی عملکرد ماژول موردنظر غیرقابل بررسی است!اگر در داده‌های ورودی ماژول مشکلی وجود نداشت؛ اما بعد از بررسی داده‌های خروجی یک ماژولِ نرم‌افزاری متوجه نادرست بودن آنها شدیم،‌ متوجه می‌شویم که احتمالا در فرآیند اجرای آن ماژول،‌ مشکلی وجود دارد که منجر به تولید نتایج اشتباه شده‌است. در این شرایط هم باید مراحل تست را تا زمانیکه روند اجرای ماژول را مجددا رصد کنیم، متوقف کرده و ادامه‌ی مراحل را بعد از یافتن مشکل و رفع آن پیگیری کنیم.آیا ساختمان‌داده هایی که به‌صورت محلی (local) تعریف شده‌اند،‌ در تمام طول برنامه یکپارچگی خود را حفظ می‌کنند؟همانطور که میدانید،‌ متغیرهایی که به‌صورت محلی درون برنامه تعریف می‌شوند،‌ وظیفه دارند اطلاعات را موقتا در خود نگه دارند تا پردازش دستورها و یا انتقال اطلاعات بین بخش‌های داخلی کلاس بهتر صورت بگیرد. حال اگر یک متغیر محلی یکپارچگی خود را از دست بدهد چه اتفاقی می‌افتد؟ برای مثال اگر در حین برنامه، مقدار آن به‌شکل غیرمنتظره‌ای صفر شود(یا جوری تغییر کند که در برنامه پیش‌بینی نشده است.)، تمام فرآیندهای وابسته به آن،‌ به مشکل برمیخورند و روند اجرای برنامه مختل می‌شود. چرا که متغیرهای محلی (local) تاثیر زیاد و مستقیمی بر روی متغیرهای کلی(global) برنامه می‌گذارند و اگر یکپارچگی خود را حفظ نکنند، می‌توانند در روند کلی برنامه خلل ایجاد کنند. به همین علت، ساختمان‌داده‌های محلی (local) تست می‌شوند تا اطمینان حاصل شود که داده‌های ذخیره‌شده، در تمام مراحل اجرای الگوریتم به‌طور موقت یکپارچگی خود را حفظ می‌کند. رابطه‌ی بین متغیرهای محلی(Local Variables) و متغیرهای کلی(Global Variables)شرایط مرزی در ماژول‌های دارای محدودیت،‌ خطاخیزترین بخش‌های اجرای برنامه هستند! آزمایش مرزهای عملکردی ماژول‌های مختلف، یکی از مهمترین وظایف واحد آزمایش است. یکی از جاهایی که اغلب برنامه ها شکست می‌خورند، در مرزهای مشخص‌شده برای آنها است. برای مثال بیشتر خطاها هنگامی رخ می دهند که در یک حلقه با متغیر i ، برنامه در حال بررسی آخرین مقدارهای قابل قبول برای متغیر i است و باید تصمیم بگیرد که حلقه قطع شود و یا ادامه پیدا کند؟ یا زمانیکه میخواهد عنصر nام یک آرایه n-بعدی را پردازش کند و یا هنگامی‌که در حال چک‌کردن حداکثر یا حداقل مقدارِ مجاز برای یک متغیرِخاص (که حتما باید مقادیر موجود در یک رنج مشخص را به خود بگیرد و نسبت به مقادیری که به آن نسبت‌داده می‌شود،‌ عملیات‌های مختلفی را انجام دهد)می‌باشد. در بخش‌هایی که ساختارهای شرطی گفته‌شده وجود داشته باشد؛ شرایط مرزی برنامه و محدودیت های آن مورد آزمایش قرار می گیرد تا اطمینان حاصل شود که ماژول در محدوده‌هایی که برای آن تعیین شده و با شرایطی که برای آن مشخص شده است، درست رفتار می‌کند یا خیر؟!بعضی از متغیرها،‌ بسته به مقداری که به آنها اده می‌شود، کارهای متفاوتی انجام‌دهند.باید تمام راههایی که ممکن است برنامه طی کند را خودمان یکبار طی کنیم تا مطمئن شویم که مشکلی پیش نخواهد آمد!طی‌کردن مسیرها و حالت‌های مختلف اجرای یک برنامه، یکی از ضروری‌ترین کارهایی است که باید درون Unit Test انجام شود! در حقیقت در این مرحله، تمام مسیرهای مستقل موجود در ساختار کنترل برنامه آزمایش می‌شوند تا اطمینان حاصل شود که همه دستورات در یک ماژول حداقل یکبار اجرا می شود و این دستورات، حتی اگر تنها یکبار اجرا شد هم درست اجرا می‌شود! در این فرآیند، Test case ها باید جوری طراحی شوند که مسیرهایی که ممکن‌است در آن مشکلاتی مثل اشتباه محاسباتی، اشتباه در مقایسه یا طراحی‌شدن جریان نامناسب برای پیاده‌سازی برنامه وجود داشته‌باشد را برملا کنند تا برنامه‌نویس بتواند تغییرات مورد نیاز را در آن اعمال کند. اگر در متن برنامه، دستوراتی وجود داشته باشد که در صورت تست تمام راههای ممکن،‌ حتی یک بار هم اجرا نشوند،‌ ممکن است نشان دهنده ی دو حالت زیر باشد:1- در فایل های برنامه‌ی ما کدهایی وجود دارد که از جریان برنامه اصلی خارج شده اند و اضافی می‌باشند که برای رعایت اصول تمیزی کد،‌ بهتر است آنها را برای همیشه پاک کنیم تا کد بهتری داشته باشیم.2- برنامه مشکل منطقی دارد که تمام راههایی که برای حالتهای مختلف طراحی کرده‌ایم، مورد استفاده قرار نمی‌گیرد(برای مثال به دلایل منطقی،‌یک متغیر boolean خاص همواره مقدار true را به خود می‌گیرد و هیچوقت false نمی‌شود تا کدهای مربوط به آن اجرا شود!‌ پس کدهایی که برای حالت false آن نوشته‌ایم،‌ همیشه بلا استفاده باقی می‌مانند و هیچوقت نمیتوانیم امکانی که این حالت در برنامه ایجاد می‌کند را مورداستفاده قرار دهیم.)تصویر زیر، به خوبی می‌تواند شرایط بالا را توصیف کند. در این تصویر،‌ یک متغیر به نام flag تعریف شده‌است که &quot;عمدا&quot; طوری تنظیم شده‌است که همواره دربرگیرنده‌ی مقدار true باشد. تابع این کد را به وسیله‌ی JUnit‌و در محیط  intelliJ IDEA به‌شکلی اجرا کرده‌ایم که code coverage را نیز لحاظ کند و شکل زیر،‌خروجی HTML حاصل از اجرای‌این فرآیند است. همانطور که در تصویر می‌بینید،‌ با استفاده از کد رنگ سبز و قرمز،‌ مشخص شده‌است که حالت else شرط مورد نظر هیچگاه اجرا نمی‌شود و این مسئله برای برنامه نویسِ این بخش،‌ یک زنگ خطر محسوب می‌شود. نمونه‌ای از خروجی HTML حاصل از اجرای تست تابع (با قابلیت coverage) در محیط intelliJ IDEAبرای درک بهتر حالت‌های مختلف اجرای برنامه،‌ State Diagramها بهترین ابزار هستند.برای بهتر درک کردن مسیرهای متفاوت نرم‌افزار و طراحی دقیق‌تر test caseها ، بهتر است از  state diagram  یا دیاگرام‌های حالت، ‌استفاده کنیم. چراکه این دیاگرام‌ها، علاوه براینکه می‌توانند برای درک جریان عملکردیِ حالتهای ممکنِ اجرای نرم‌افزار به ما کمک کنند؛ این امکان را ایجاد می‌کند که به کمک قوانین جبرفرآیندی (Process Algebra) و نظریه‌ی ماشین‌ها،‌ تمام حالتهای ممکن در جریان اجرای برنامه را ارزیابی کرده و از درست‌بودن عملکرد آنها مطمئن شویم. اگر کلاسی که میخواهیم بررسی کنیم، با کلاس های دیگری نیز همکاری می کند و در ارتباط است، تعداد این دیاگرام های حالت بیشتر از یکی می شود و باید تمام آنها را در کنار هم بررسی کنیم تا جریان رفتاری نرم افزار را متوجه شویم و تمام حالات ممکن را در نظر بگیریم.یک نمونه‌ی ساده از یک State Diagramنرم‌افزار نهایی،‌ نه تنها باید درست کار کند؛ بلکه حتی باید درست خطا بدهد!وقتی حتی خطاها هم باید درست باشد!یک طراح نرم‌افزارِ خوب و دقیق، می تواند شرایطی که ممکن است برنامه‌‌ی درحال توسعه‌اش در آنها به مشکل بربخورد را پیش‌بینی کرده و مسیرهای مدیریت خطا را برای هرکدام از شرایطِ ممکن، طراحی کند . این مسیرهای مدیریت خطا، گاهی ممکن است شامل تغییر مسیر برنامه از جریانِ عادیِ خود باشد و گاهی منجر به متوقف شدن تمام پردازش‌ها شود تا به این‌ وسیله، از بروز مشکلات جدی‌تری برای برنامه جلوگیری کند. این روش antibugging یا ضد خطا هم نامیده می شود. متأسفانه، علی‌رغم اینکه اهمیت رفع‌کردن خطاها غیرقابل انکار است و بخشی از کدهای هر برنامه‌ای، صرف رفع خطا می شود؛ معمولا هیچ وقت این استراتژی‌های رفع خطا تست نمی شوند تا مشخص شود که آیا این روش‌ها،‌ واقعا می‌توانند خطاهای ایجاد شده در جریان برنامه را کنترل کنند یا خیر؟! درصورتیکه ما همان‌قدر که باید مطمئن باشیم برنامه درست کار میکند،‌ باید مطمئن باشیم که از پس مشکلات و خطاهایی که ممکن است برایش پیش بیاید نیز به تنهایی برمی‌آید و اجرای آن متوقف نمی‌شود. در نتیجه حتی برای اعتبارسنجی راههای رفع خطا هم باید تست نوشته شود تا نحوه‌ی عملکرد آنها سنجیده شود. اگر این اتفاق نیفتد، طبق همان اصلی که درباره ی اهمیت تست نویسی گفتیم، ممکن است مشتری، خطاهایی را که از زیر دست برنامه‌نویس‌ها و تیم توسعه و تست در رفته است را  پیدا کند و همین اتفاق، باعث بروز خسارات مادی و معنوی زیادی برای تیم توسعه شود.خطاها باید چه ویژگی‌هایی داشته باشند تا بگوییم &quot;خطاها خوب مدیریت شده اند&quot;؟برنامه نباید به هیچ وجه زیر بار خطاها کمر خم کند!در بخش قبل، درباره‌ی پیش‌بینی خطاها و مدیریت آنها صحبت کردیم و گفتیم که همانطور که ما باید کدهای یک برنامه را تست کنیم،‌ باید خطاهای برنامه را نیز تست کنیم تا مطمئن شویم خطاها به اندازه‌ی کافی خوب و درست مدیریت شده اند! اما سوالی که پیش می‌آید،‌ این است که در این شرایط،‌ ما باید چه تست‌هایی روی خطاها انجام دهیم و از چه جهاتی آنها را تست کنیم؟ به عنوان پاسخ برای این سوال،‌ چند نمونه از پاسخ‌هایی که ممکن است در صورت مدیریت نادرست خطاها، در هنگام تست ایجاد بشود را نام می‌بریم:1. شرح خطا نامفهوم است.خطایی که در برنامه پیش می‌آید،‌ باید جوری شرح داده شود که مخاطب آن (که بسته به نوع و دلیل وقوع خطا،‌ ممکن است کاربر یا مسئول مانیتور سیستم یا مسئول بخش‌های مختلف تیم توسعه و یا حتی برنامه نویس باشد) کاملا متوجه مفهوم آن شود و بتواند آن را رفع کند.2. خطای ذکر شده با خطای روی داده مطابقت ندارد.شرح خطا باید دقیق باشد و کاملا متناسب با اتفاقی که پیش آمده است اتفاق بیفتد. در غیراینصورت،‌ باعث گیج شدن افراد و طولانی شدن فرآیند رفع خطا می‌شود.3. شرایط خطا باعث دخالت سیستم قبل از رسیدگی به خطا می شود.وقتی خطا رخ می دهد، نرم‌افزارِ توسعه‌داده‌شده باید بتواند جریان عملکردی خود را طوری مدیریت کند که کل برنامه از کار نیفتد. اما برخی خطاها هستند که اگر اتفاق بیفتند،‌ سیستم‌عاملِ دستگاهی که برنامه روی آن درحال اجرا است (قبل از اینکه برنامه فرصت پیدا کند که متوجه شرایط بشود و کدهای مربوط به مدیریت آن را اجرا کند)، برنامه‌ی مورد نظر را به صورت کامل متوقف می‌کند. به این خطاها،‌ خطاهای مرگبار یا &quot;Fatal Error&quot; می‌گویند. این اتفاق در دنیای توسعه‌ی نرم‌افزار اصلا قابل قبول نیست و به هیچ‌وجه نباید رخ دهد بلکه هر نرم‌افزاری باید درصورت وقوع مشکل،‌ فرصت گزارش و یا حل خطای پیش آمده را داشته باشد و جوری روند اجرا را مدیریت کند که برنامه متوقف نشود و بعد از مدیریت شدن خطا، ادامه‌ی کارش را انجام دهد.البته حتی با این وجود،‌ بازهم ممکن است خطاهای خیلی بزرگی رخ دهد که باعث بسته شدن برنامه شود! باید توجه داشته‌باشیم که حتی اگر خطای خیلی بزرگ و غیرقابل پیش‌بینی‌ای رخ داده بود؛‌ به طوریکه به هیچ‌وجه نمیتوانستیم جلوی وقوع آن را بگیریم هم،‌ حداقل باید بتوانیم خودمان با روشی که تجربه‌ی کاربری بدی ایجاد نکند،‌ برنامه را ببندیم و خطای پیش آمده، باعث بسته‌شدن آن توسط سیستم‌عامل (یا به اصطلاح crashکردن برنامه) و یا ساخته شدن خروجی های نادرست نشود!4. پردازش exception نادرست است.هر خطایی که در برنامه رخ می‌دهد،‌ باید با روشی که با دلیلِ ایجادِ آن متناسب است، مدیریت شود. اگر در هنگام تست،‌ این پیام به ما داده شود، به این معناست که exception های ایجادشده، به درستی مدیریت نشده اند و دستورات نوشته شده برای مدیریت آنها‌، نمی‌توانند مشکل پیش آمده را رفع کرده و از به دردسر افتادن سیستم جلوگیری کند.5. شرح خطا، اطلاعات کافی برای کمک به محل علت خطا ارائه نمی دهد.همانطور که در مورد 1 هم توضیح دادیم، اطلاعات خطا باید جوری باشد که بتواند به مخاطب خود بگوید که دقیقا چه اتفاقی افتاده است و این خطاها توسط کدوم کلاس‌ها یا ماژول‌های نرم‌افزاری تولید شده اند. در غیراینصورت ممکن است فرآیند رفع خطا‌، بارها و بارها پیچیده‌تر شود و مشکل پیش‌آمده،‌به سختی رفع شود.Source : Roger S. Pressman, Bruce R. Maxim. &quot;Software Engineering A Practtitioner&#x27;s Approach&quot; - 9th Editionدر مقاله‌ی بعدی،‌ درباره‌ی دو استراتژی مهم در تست نرم‌افزار،‌ یعنی استراتژی جعبه‌ی سفید و استراتژی جعبه‌ی سیاه صحبت می‌کنیم. این دو استراتژی،‌ یکی از جالب‌ترین مباحث در زمینه‌ی تست نرم‌افزار هستند. پیشنهاد می‌کنم مقاله‌ی بعد را حتما مطالعه کنید.</description>
                <category>محدثه سالم</category>
                <author>محدثه سالم</author>
                <pubDate>Fri, 19 Nov 2021 17:07:07 +0330</pubDate>
            </item>
                    <item>
                <title>تست‌ها، مسئول محافظت از اجرای نیازمندی‌های اصلی نرم‌افزار</title>
                <link>https://virgool.io/CE-SHAHED-publication/%D8%AA%D8%B3%D8%AA-%D9%87%D8%A7-%D9%85%D8%B3%D8%A6%D9%88%D9%84-%D9%85%D8%AD%D8%A7%D9%81%D8%B8%D8%AA-%D8%A7%D8%B2-%D9%86%DB%8C%D8%A7%D8%B2%D9%85%D9%86%D8%AF%DB%8C-%D9%87%D8%A7%DB%8C-%D8%A7%D8%B5%D9%84%DB%8C-%D9%86%D8%B1%D9%85-%D8%A7%D9%81%D8%B2%D8%A7%D8%B1-haiub49tqwh5</link>
                <description>در بخش قبلی این سری مقاله،‌ درباره‌ی اهمیت و ضرورت تست نرم‌افزار صحبت کردیم و متوجه شدیم که اگر قبل از انتشار نرم‌افزار و رسیدن آن به دست کاربر،‌ ایرادات موجود در پروژه را متوجه نشویم؛‌ به احتمال زیاد، کاربر در حین کارکردن با نرم‌افزار ما، به مشکل پی میبرد و آن زمان است که دیگر آب رفته به جوی بازگردانده نمی‌شود و بسته به اینکه مشکل پیش آمده برای او،‌ تا چه حد مهم و بزرگ باشد؛ میتواند باعث بی‌اعتمادی کاربر به محصول نرم‌افزاری ما و احیانا تبلیغات منفی علیه آن شود و این اتفاق، در طولانی مدت خسارات کوچک و بزرگ اقتصادی و اجتماعی زیادی را برای شرکت به همراه دارد. پس بهتر است قبل از اینکه برای درمان این خسارات هزینه کنیم،‌ بودجه‌ای را برای پیشگیری کنار بگذاریم چراکه به هرحال، به‌مراتب بهتر از درمان است.قبل از اینکه کدهای برنامه توسعه داده شود،‌ به فکر تست‌کردن آن باشید!یکی از رویکرد های خیلی‌خوبی که در توسعه‌ی یک نرم‌افزار وجود دارد،‌ این است که قبل از توسعه‌ی یک برنامه، unit test case های مربوط به آن را طراحی کنیم. یعنی در هنگام طراحی معماری‌ها و طرح‌های اولیه‌ی نرم‌افزار،‌ برای هر بخش مشخص کنیم که: (اگر این بخش از برنامه به چه نتیجه ای برسد،‌ ما خواهیم گفت که کار خود را به خوبی انجام داده است؟!) این کار باعث می‌شود که هم در حین طراحی معماری نرم‌افزار و هم در هنگام توسعه ی کدها، ذهنیت بهتری درباره ی هربخش داشته باشیم و بدانیم بخش موردنظر را چطور توسعه بدهیم تا انتظاراتی که طراحان برنامه از آن دارند (و درون تست ها، به روشنی آن را توصیف کرده اند) برآورده شود. به همین دلیل،‌ قبل از اینکه درباره‌ی انواع مختلف تست صحبت کنیم‌، ابتدا مراحل تولید و طراحی یک نرم‌افزار را به‌طور کلی مرور می‌کنیم تا بتوانیم دید بهتری درباره ی انواع مختلف تست‌های مورد نیاز داشته باشیم.مراحل طراحی یک محصول نرم‌افزاریداستان طراحی یک نرم‌افزار،‌ از اینجا شروع می‌شود که ابتدا صاحبان یا ذی‌نفعان نرم‌افزار موردنظر،‌ با مدیر فنی تیمی که میخواهند مسئولیت توسعه‌ی نرم‌افزار را به آنان بسپرند،‌ یک جلسه میگذارند و در آن،‌ تمام ویژگی‌هایی که میخواهند محصول نهایی داشته باشد را به همراه ملاحظاتی که از نظر بودجه، سیاست‌های شرکت یا سازمان موردنظر و یا موراد مشابه دارند را برای او شرح می‌دهند. مدیرفنی تیم توسعه‌ی نرم‌افزار موظف است خواسته‌های آنان را بشنود و باتوجه به این خواسته‌ها، الزامات عملکردی نرم‌افزار را به همراه تکنولوژی‌هایی که میتواند به بهترین شکل خواسته‌های کارفرما را برآورده کند، انتخاب کند.در مرحله‌بعد،‌ اعضای تیم مدیریت پروژه وظیفه دارند خواسته‌های کارفرما (‌که لزوما خواسته‌های تکنیکی‌ای نیستند) را  به صورت نیازمندی‌های سیستم و به نحوی که روشن و قابل پیاده‌سازی باشد‌،در قالب نیازمندی‌های سیستم بیان کنند. تا این مرحله،‌ قاعدتا اطلاعات کلی نرم‌افزار استخراج شده است و حال نوبت آن است که بیشتر وارد جزئیات فنی شویم. برای این کار،‌ ابتدا باید معماری بخش‌های مختلف برنامه توسط معمار‌ نرم‌افزار ایجاد شده و سپس اسناد طراحی شده برای پیاده‌سازی نهایی به دست برنامه‌نویس‌ها سپرده شود تا مراحل تولید برنامه آغاز شود.شکل 1 - مراحل تست یک پروژه‌ی نرم‌افزاری،‌کاملا متناظر با مراحل تولید آن است.در شکل بالا که به‌خوبی میتواند ارتباط بین مراحل تولید و تست نرم‌افزار را نشان دهد؛‌ مطابق توضیحات بخش قبل،‌ دیده می‌شود که برای تولید یک نرم‌افزار از بیرونی ترین حلقه به سمت درونی‌ترین حلقه میرویم و مراحل را یک به یک پیاده سازی می‌کنیم. اما هنگامیکه نوبت به تست نرم‌افزار برسد،‌ دقیقا برعکس جریان پیش میرویم و مراحل تست را از درونی‌ترین حلقه به بیرونی‌ترین حلقه طی می‌کنیم تا فرآیند تست از همه ی جوانب کامل شود.مرحله اول) تست اجزاء برنامه یا Unit Testابتدایی ترین مرحله‌ی تست،‌ Unit Test است که مطابق با مرحله‌ی پیاده‌سازی کدها در مارپیچ شکل 1 می‌باشد. همانطور که از این بخش مشخص است؛ در Unit Test،‌ تمرکز ما بر این است که مطمئن شویم تک‌تک اجزای مستقل کد،‌ اولا درست و منطقی کار می‌کنند و دوما کاری را که انتظار داریم انجام دهند را به‌خوبی و کامل انجام می‌دهند. البته باید بگوییم که در این تست،‌ منظورمان از یک Unit دقیقا یک متغیر،‌ یک متد و یا حتی لزوما یک کلاس نیست! بلکه در هر بخش و با توجه به ساختار برنامه می‌تواند تعبیر ما از یک Unit متفاوت باشد. برای مثال ممکن است گاهی تنها یک متد را به عنوان یک یونیت تست کنیم و گاهی نیاز است چند کلاسِ به هم مرتبط را یک واحد در نظر بگیریم و آنها را مورد آزمایش قرار دهیم.مرحله دوم) تست یکپارچگی یا Integration Testپس از آنکه مطمئن شدیم تک‌تک بخش های برنامه درست و خوب کار می‌کند،‌ حال نوبت آن است که این بخش های مختلف را کنار هم قرار دهیم تا متوجه شویم که آیا این بخش‌ها میتوانند در کنار یکدیگر نیز به خوبی کار کنند و نتیجه‌ای که انتظار داریم از همکاری آنها حاصل شود را تولید کنند یا خیر؟! همانطور که از شکل 1 مشخص است،‌ این مرحله از تست متناظر با طراحی معماری نرم‌افزار است و قاعدتا در این مرحله انتظار داریم تست‌های طراحی شده مشخص کنند که آیا معماری ای که برای نرم‌افزار طراحی کرده ایم،‌ به‌خوبی و درست پیاده سازی شده است یا خیر؟ همچنین اگر در ارتباط بین بخش های مختلف برنامه،‌ مشکلی وجود داشته باشد؛ در این مرحله از تست متوجه می‌شویم و آن را رفع می‌کنیم.مرحله سوم) تست اعتبار سنجی یا Validation Testزمانی که به این مرحله از تست وارد می‌شویم، تقریبا مطمئن هستیم که نرم‌افزار تولید شده،‌ از نظر فنی و منطقی کاملا خوب و درست کار می‌کند. در این مرحله نوبت این است که متوجه شویم که آیا این محصول نرم‌افزاری تولید شده،‌ دقیقا همان چیزی است که کارفرما یا ذی‌نفعان سیستم انتظار داشته اند یا خیر؟! همانطور که از مارپیچ شکل 1 مشخص است، در این مرحله ویژگی‌های محصول نهایی را با نیازمندی‌هایی که در ابتدا برای سیستم در نظر گرفته شده اند تطبیق می‌دهیم تا مطمئن باشیم که تمام ویژگی های رفتاری و عملکردی مورد نظر، در نرم‌افزار پیاده شده باشد و قابلیتی وجود نداشته باشد که نادیده گرفته شده و یا به اشتباه پیاده سازی شده باشد.مرحله چهارم) تست کل سیستم یا System Testدر مرحله ی آخر فرآیند تست نرم‌افزار، کار انجام تست از مبحث مهندسی نرم‌افزار فراتر می رود و وارد مهندسی کامپیوتر می شود. در مرحله‌ی System Testing ، سیستمی که تقریبا مطمئنیم به تنهایی درست و خوب کار می‌کند، با سیستم‌های دیگری که در دنیای واقعی باید در کنار آنها خوب کار کند، ترکیب می شود تا سنجیده شود که آیا این واحدهای مستقل، می توانند درکنار یکدیگر نیز خوب و بدون مشکل کار کنند یا خیر؟! برای مثال اگر نرم‌افزار ما نیاز داشته باشد برای انجام کارهای خود،‌ از دیتابیس‌ها یا سرورهای‌خارجی دیگری استفاده کند و یا با سامانه‌های دیگری تعامل کند،‌ باید قبل از انتشار آن مطمئن شویم که در واقعیت نیز می‌تواند این کار را به‌خوبی انجام دهد و این وظیفه‌ی تست سیستم می‌باشد. برای انجام تست سیستم، قاعدتا به افراد باتجربه‌ای نیاز داریم که دید نسبتا خوبی نسبت به بخش‌های مختلف سیستم موردنظر داشته باشند تا بتوانند از درست‌بودن عملکرد آنها مطمئن شوند.Source : Roger S. Pressman, Bruce R. Maxim. &quot;Software Engineering A Practtitioner&#x27;s Approach&quot; - 9th Editionدر مقاله ی بعدی،‌ بیشتر روی Unit Test تمرکز می‌کنیم و درباره‌ی جزئیات آن،‌ بیشتر صحبت می‌کنیم. توصیه می‌کنم اگر این بحث‌، تا اینجا برایتان جذاب بوده‌، با من همراه باشید.</description>
                <category>محدثه سالم</category>
                <author>محدثه سالم</author>
                <pubDate>Thu, 11 Nov 2021 01:11:02 +0330</pubDate>
            </item>
                    <item>
                <title>تست نرم افزار چیست؟ آیا تست‌کننده ها و توسعه‌دهنده‌ها باهم در رقابت اند؟</title>
                <link>https://virgool.io/@mohsal110/%D8%AA%D8%B3%D8%AA-%D9%86%D8%B1%D9%85-%D8%A7%D9%81%D8%B2%D8%A7%D8%B1-%DA%86%DB%8C%D8%B3%D8%AA-%D8%A2%DB%8C%D8%A7-%D8%AA%D8%B3%D8%AA-%DA%A9%D9%86%D9%86%D8%AF%D9%87-%D9%87%D8%A7-%D9%88-%D8%AA%D9%88%D8%B3%D8%B9%D9%87-%D8%AF%D9%87%D9%86%D8%AF%D9%87-%D9%87%D8%A7-%D8%A8%D8%A7%D9%87%D9%85-%D8%AF%D8%B1-%D8%B1%D9%82%D8%A7%D8%A8%D8%AA-%D8%A7%D9%86%D8%AF-cwhing1ctn7r</link>
                <description>در این مقاله،‌ میخواهیم درباره ی تست نرم‌افزار صحبت کنیم. احتمالا حتی اگر کسی که در زمینه‌های کامپیوتری کار نمی‌کند و در این زمینه، دانش خاصی ندارد هم موضوع بحث ما را بشنود،‌میتواند حدس بزند که ما میخواهیم درباره ی چه چیزی صحبت کنیم؟! بله؛ ما میخواهیم بررسی کنیم که با استفاده از چه راههایی می‌توانیم مطمئن شویم که برنامه ی ما اولا؛ از نظر منطقی درست کار می کند و دوما؛ تمام قابلیت هایی که بخاطر آنها طراحی شده است را میتواند پشتیبانی کند. اما این مسئله،‌ شاید فقط از دور اینقدر زیبا و منطقی به نظر بیاید و بعد از اینکه کمی وارد دنیای برنامه‌نویسی شدیم و روی توسعه ی نرم افزارهای مختلف تمرکز کردیم، متوجه شویم که نقاط مبهم زیادی درباره ی تست نرم‌افزار وجود دارد. در این سری مقاله سعی میکنیم،‌ آن نقاط مبهم را بشناسیم و آنها را رفع کنیم.چرا باید نرم افزاری که در هنگام توسعه، بارها اجرا شده و عملکرد آن کاملا تست شده است را دوباره تست کنیم؟همانطور که در مقدمه گفتیم؛ تست نرم‌افزار، از دور خیلی مقوله‌ی منطقی و خوب و ضروری ای به نظر میرسد. اما اگر فردی که تازه وارد دنیای نرم‌افزارهای کامپیوتری شده است،‌ شروع به برنامه‌نویسی و توسعه نرم‌افزارهای کوچک یا بزرگ در قالب گروههای فردی یا کوچک کند؛ ممکن است در مواجهه با تست نرم افزار به این موضوع فکر کند که چرا باید نرم‌افزاری که در حین توسعه،‌ بارها و بارها اجرا شده و ایرادات و خطاهای آن رفع شده را دوباره تست کنند؟ چرا این تست را در مواردی با کد های مخصوص و به صورت اتوماتیک انجام می دهند؟ چرا در شرکت های بزرگ، اصولا یک فرد یا یک گروه را استخدام میکنند که فقط خطاها و ایرادات برنامه را بگیرند؟ آیا این کار برای به چالش کشیدن توانایی های فرد برنامه‌نویس است یا خیر؟! برای رسیدن به پاسخ این سوالات، پیشنهاد می‌کنم تا انتهای این مقاله صبر کنید.تست نرم‌ افزار چیست؟تست نرم‌افزار شامل مجموعه عملیات‌هایی است که انجام می‌شود تا به ما این اطمینان را بدهد که اولا؛ برنامه ی توسعه‌ داده شده،‌از نظر منطقی و عملکردی درست کار میکند و دوما؛ این نرم‌افزار ،‌تمام قابلیت‌هایی که کارفرما یا ذی‌نفعان نرم‌افزار از آن میخواهند را برآورده می‌کند. به عبارت دیگر،‌نرم‌افزار ایجاد شده دقیقا همان چیزی است که آن ها میخواهند. این عملیات ها ممکن است شامل یکسری کدهای تست خودکار باشد که در کنار کد اصلی برنامه توسعه داده می‌شود و برای توسعه ی آنها باید از فریم ورک های مخصوص استفاده کنیم.  یا حتی ممکن است شامل یکسری فرآیند جانبی باشد؛ برای مثال در مراحلی از تست،‌ فرد یا افرادی مامور میشوند که خود را به جای کاربر بگذارند و به جای او،‌ با نرم‌افزار شما کار کنند و ایراداتی که می‌بینند را گزارش کنند تا در مراحل بعدی توسعه آنها را بهتر کنید.قانون طلایی تست نرم‌افزارقانون طلایی تست نرم‌افزارحتما شنیده اید که میگویند،‌ بهترین دوست هرکس،‌ کسی است که عیب هایش را به او هدیه بدهد. در بحث تست نرم‌افزار هم،‌ یک قانون طلایی وجود دارد که براساس همین مفهوم ایجاد شده است و باعث می شود اهمیت تست نرم‌افزار را بهتر درک کنیم. این قانون می گوید که : (اگر تیم توسعه ی یک نرم‌افزار،‌ خطاهای برنامه را پیدا نکنند؛‌ قطعا مشتری آن را پیدا میکند و آن زمان، دیگر برای جلوگیری از عواقب خیلی‌ بد فاش‌شدن آن خطا،‌ خیلی دیر است!) وقتی خطایی در برنامه وجود داشته باشد و تیم توسعه نتوانند تا قبل از انتشار محصول نرم‌افزاری به آن پی ببرند و این خطا،‌ توسط کاربر نرم افزار کشف شود؛ اتفاقی که می افتد این است که احتمالا آن کاربر مشخص،‌ دیگر نمیتواند به نرم‌افزار شما اعتماد کند و اگر بتواند، برای اپلیکیشن شما جایگزینی پیدا کند یا حتی کارش را بدون برنامه ی شما انجام دهد؛‌ احتمالا نه تنها نرم‌افزار شما را برای همیشه از روی دستگاه خود پاک میکند،‌ بلکه ممکن است تا جاییکه بتواند به اطرافیان نیز توصیه کند که از نرم‌افزار شما استفاده نکنند و به جای آن،‌ از راههای جایگزینی که وجود دارد استفاده کنند. و به این ترتیب،‌ شما بدون آنکه متوجه شوید دقیقا چه اتفاقی افتاده است،‌ تعدادی از کاربران خود را از دست داده اید و مقدار زیادی تبلیغات منفی یا بی‌اعتمادی را برای شرکت خود خریده اید که قطعا در طولانی مدت،‌ روی وضعیت اقتصادی و اعتبار شرکت شما،‌ بی تاثیر نخواهد بود.برای شناسایی چه نوع خطاهایی تست می‌نویسیم؟خطاهایی که به وسیله ی استراتژی های تست، سعی میکنیم آنها را کشف کنیم،‌به دو دسته ی کلی تقسیم می شوند:1- خطاهایی که ممکن است در هنگام توسعه‌ی نرم‌افزار، به طور ناخواسته و به دلیل اشتباه برنامه‌نویس رخ داده باشد که قاعدتا خطاهایی هستند که تیم توسعه‌دهنده، از وجودشان اطلاعی ندارد که بتواند آن ها را برطرف کند.(چون اگر اطلاع پیدا می‌کرد،‌ قاعدتا آن را تا قبل از انتشار نسخه‌ی نهایی نرم‌افزار رفع کرده بود و اکنون مشکلی وجود نداشت.)2- خطاهایی که به رفتار کاربر در نرم‌افزار مربوط می‌شود. برای مثال،‌ در جاهایی که کاربر باید ورودی خاصی وارد کند، ممکن است به هر دلیلی نتواند ورودی را با فرمتی که برنامه نویس انتظار داشته و روند برنامه را با توجه به آن چیده است وارد کند و در نتیجه روند برنامه مختلط شود.در بین افراد موجود در تیم توسعه ی نرم‌افزار،‌ چه کسی مسئول انجام فرآِیند تست است؟برای هر پروژه نرم افزاری ، قاعدتا با توجه به تفاوت در پست های افراد، نگرش های متفاوتی نسبت به تست وجود دارد که عملیات تست کردن را تحت تاثیر قرار می دهد. به طور کلی دو گروه اصلی وظیفه دارند کل فرآیند تست را انجام دهند : توسعه‌دهندگان و گروه تست نرم‌افزار.1- توسعه‌دهندگان سیستمقاعدتا معقول‌ترین انتخاب این است که برای تست یک نرم‌افزار، در ابتدا به سراغ توسعه دهندگان آن برویم؛ چراکه توسعه‌دهندگان یک نرم‌افزار،‌ بهترین افرادی هستند که ساختار آن را کاملا می‌شناسند و می‌توانند ایرادات موجود در آن را رفع کنند.اما چالشی که در این مرحله وجود دارد این است که اگر از افرادی که نرم‌افزار را توسعه داده‌اند، خواسته شود که یک دور دیگر کل نرم‌افزار را تست کنند؛ طبیعتا خواهند گفت که اطمینان دارند که برنامه‌ای که ساخته اند بی‌نقص بوده و کاملا طبق نیاز مشتری و چیزی که با توجه به برنامه و بودجه‌ی پروژه از آنها خواسته شده است، کار می‌کند. البته این نوع نگاه، از نظر روانشناسی کاملا طبیعی است. چراکه توسعه دهندگان هر سیستمی، در زمان توسعه، مستندسازی و ساخت یک برنامه، هیچوقت از عمد کاری انجام نمی دهند که برنامه ایرادی پیدا کند. همچنین در حین توسعه هم قدم‌به‌قدم برنامه را تست می کنند و تا جایی که امکان دارد، از درست بودن عملکرد آن اطمینان پیدا می کنند. اما واقعیت این است که حتی با بالاترین دقت ها هم، تقریبا همواره تعدادی خطا کشف نشده باقی‌ می‌مانند. پس حتی اگر خطایی هم باقی مانده باشد،‌ حتما خطایی بوده است که برنامه‌نویس نتوانسته‌است آن را پیدا و رفع کند و به همین دلیل، تیم مدیریت پروژه نباید اهمیت تست نرم‌افزار را نادیده بگیرد و صرف تایید توسعه‌دهندگانِ خود و پایان یافتن فرآیند توسعه‌ی نرم‌افزار،‌ برنامه را کاملا درست و بدون خطا در نظر بگیرد و از تست دوباره ی نرم‌افزار چشم‌پوشی کند. چرا که طبق قانون طلایی تست نرم‌افزار که در بخش قبل به آن اشاره کردیم؛ در صورتیکه خطایی وجود داشته باشد که توسط تیم سازنده‌ی برنامه کشف نشده باشد، مشتری آن را کشف می کند و در آن صورت، اعتبار شرکت زیر سوال خواهد رفت.2- تیم مستقل تست نرم‌افزار در کنار توسعه دهندگان، گروهی هم هستند که اصولا برای این استخدام می‌شوند که خطاهای برنامه را پیدا کنند. این گروه که اختصارا آنها را ITG(Independent Test Group) می گویند، وظیفه دارند خطاهایی را که توسط برنامه نویس حل نشده اند را پیدا کرده و آنها را گزارش کنند. البته قاعدتا اینطور نیست که جریان برنامه بعد از گزارش شدن خطاها و مشکلات توسط گروه ITG رها شود! بلکه تیم آزمایشگر باید به طور مداوم با تیم توسعه‌دهنده در تعامل باشند و مشکلات را گزارش کنند تا تیم توسعه بتوانند آنها را رفع کنند.سه تصور غلط درباره ی تست نرم‌افزارشاید از دور انتظار داشته باشیم ارتباط بین توسعه دهنده،‌تست کننده و مدیر مثل عکس بالا باشد؛‌اما در واقعیت،‌لزوما اینطور نیست :)سه تصور غلط در زمینه‌ی تست‌کردن وجود دارد که به‌دلیل تفاوت در دیدگاه افرادیکه در تیم توسعه‌ی نرم‌افزار نقش‌های متفاوتی دارند،‌ ایجاد شده است. در این بخش میخواهیم این سه دیدگاه غلط را بشناسیم و آنها را اصلاح کنیم:1- وظیفه ی برنامه نویس، تنها توسعه ی نرم افزار است و نیاز نیست هیچ تستی بنویسد.--&gt; همانطور که در بخش‌های قبل نیز به آن اشاره شد،‌ بخش مهمی از مراحل تست برنامه برعهده ی برنامه‌نویس‌ها است و توسعه دهنده های هر نرم‌افزار باید بخش زیادی از تست ها (بخصوص تست هایی که برای اعتبار سنجی شرایط حساس در جریان اجرای برنامه یا شرط های مرزی حلقه ها و دستورهای کنترلی و یا رفتار کاربر می شود) را درحین توسعه، پیاده سازی کنند.2- زمانی که برنامه در حال تست توسط یک آزمایشگر خارج از تیم توسعه است، حتما باید به دلایلی شکست بخورد.--&gt; در مواقعیکه کار تحلیل نرم‌افزار خیلی دقیق و منظم پیش برود و برنامه چندبار مورد تست قرار بگیرد،‌ ممکن است دیگر در نرم‌افزار خطا یا ایراد خاصی وجود نداشته باشد. این دیدگاه که تیم تست نرم‌افزار حتما باید یک یا چند ایراد پیدا کند وگرنه انگار کار خود را به خوبی و درست انجام نداده است،‌کاملا غلط می باشد و مبنای دقیقی ندارد.3- افراد مسئول تست برنامه، تنها زمانی به پروژه اضافه می شوند که پروژه تکمیل شده است. و در حین توسعه هیچ تستی انجام نمی شود.--&gt; اگر بعد از گذراندن زمان نسبتا زیادی که برای توسعه‌ی نرم‌افزار مورد نظرمان صرف شده است،‌ آن را به دست تیم تست‌کننده‌ی نرم‌افزار بسپاریم؛ باعث می‌شود زمان تحویل و انتشار فایل نهایی پروژه به شدت طولانی تر شود. چراکه بعد از تحلیل نرم‌افزار و گزارش‌شدن خطاها،‌ این ایرادات باید دوباره به سمت تیم توسعه‌دهنده برگردد تا اصلاح شود. و دوباره مدت طولانی ای طول می کشد تا نسخه ی بعدی نرم افزار آماده و برای بررسی مجدد تیم تست ارسال شود. در نتیجه انتشار برنامه مدت زیادی عقب می افتد. در صورتیکه برای انجام خیلی از تست ها‌، هیچ ضرورتی وجود ندارد که تا توسعه ی کامل برنامه منتظر بمانیم و میتوان همزمان با کار تیم توسعه،‌ مراحل تست را هم انجام داد و در زمان صرفه جویی کرد.از کجا بفهمیم که مراحل تست یک نرم‌افزار کاملا انجام شده است و نیازی به ادامه دادن آن نیست؟تا کجا باید مراحل تست را انجام دهیم؟یکی از سوالات رایجی که در هنگام تست نرم‌افزار پرسیده می شود، این است که از کجا بفهمیم که تست به خوبی انجام شده است؟ یا از کجا بفهمیم که تست کردن برنامه کافیست و دیگر نیازی به انجام تست های بیشتر نیست؟متاسفانه جواب مشخص و از پیش تعیین شده‌ای برای این سوال وجود ندارد. اما چند پاسخ عملی که حاصل تجربه های عملی تست‌کننده‌ها است وجود دارد که می توانند برای پیدا کردن پاسخ به شما کمک کنند:- به عنوان اولین پاسخ،‌ باید بگوییم که : شما هیچوقت نمیتوانید ادعا کنید که عملیات تست کردن کامل انجام شده است! چراکه حتی اگر از درست‌بودن عملکرد بخش‌های مختلف برنامه مطمئن باشید، بازهم هر باری که کاربر برنامه را اجرا می کند، میتوانیم بگوییم که برنامه ی شما در حال آزمایش است و هرلحظه ممکن است به هر دلیلی در روند اجرای آن خطا رخ دهد! این حقیقت تلخ، در واقع اهمیت این موضوع را میرساند که شما باید تا جای ممکن تضمین کنید که با احتمال بالایی هیچ خطای غیرمنتظره و بررسی‌نشده ای رخ نمی‌دهد تا کمترین احتمال برای پیدا شدن خطاهای جدید باقی بماند. - پاسخ دیگری که در این باره وجود دارد و تاحدودی بی رحمانه اما در عین حال منطقی است، این است که: هر زمانی که قراردادی که برای پشتیبانی نرم افزار بسته اید به پایان رسید یا از شرکت مورد نظر استعفا دادید و یا کارفرما آنقدر دچار محدودیت شد که درخواست پشتیبانی نرم‌افزار را لغو کرد،‌ کار شما به عنوان تست‌کننده تمام می شود. البته در این صورت،‌ باز هم این مراحل فقط برای شما تمام می‌شود نه برای صاحبین نرم‌افزار!Source : Roger S. Pressman, Bruce R. Maxim. &quot;Software Engineering A Practtitioner&#x27;s Approach&quot; - 9th Editionدر مقاله ی بعدی،‌ به معرفی مراحل تست نرم‌افزار که ارتباط تنگاتنگی با مراحل مختلف طراحی نرم‌افزار دارند،‌ می‌پردازیم. با من همراه باشید.</description>
                <category>محدثه سالم</category>
                <author>محدثه سالم</author>
                <pubDate>Tue, 09 Nov 2021 00:18:07 +0330</pubDate>
            </item>
                    <item>
                <title>دیزاین‌پترن‌ها، بهترین راه حل برای مسئله های پرتکرار</title>
                <link>https://virgool.io/@mohsal110/%D8%AF%DB%8C%D8%B2%D8%A7%DB%8C%D9%86-%D9%BE%D8%AA%D8%B1%D9%86-%D9%87%D8%A7-%D8%A8%D9%87%D8%AA%D8%B1%DB%8C%D9%86-%D8%B1%D8%A7%D9%87-%D8%AD%D9%84-%D8%A8%D8%B1%D8%A7%DB%8C-%D9%85%D8%B3%D8%A6%D9%84%D9%87-%D9%87%D8%A7%DB%8C-%D9%BE%D8%B1%D8%AA%DA%A9%D8%B1%D8%A7%D8%B1-nqtkkqnryxjd</link>
                <description>دیزاین‌پترن‌ها، بهترین راه حل برای مسئله های پرتکراردیزاین‌پترن‌ها، در‌ واقع یک راه‌حل یا استراتژی اثبات‌شده برای حل‌کردن یک مسئله یا انجام یک‌ وظیفه ی مشخص در زبان های شیءگرا (object oriented) هستند. اما این الگوهای‌طراحی، تنها ایده‌ی اصلی رفع یک مشکل را بیان می‌کنند و پیاده سازی مشخص ندارند. به همین دلیل وابسته به یک زبان خاص نیستند و می‌توانند در زبان‌های برنامه نویسی مختلف استفاده شوند. استفاده از الگوهای طراحی باعث می‌شود تا کد نوشته شده، انعطاف بیشتری پیدا کرده و همچنین قابلیت نگهداری و باز استفاده کردن آن نیز افزایش یابد. جالب است بدانید که در طراحی تعداد زیادی از کلاسهای درونی زبان‌هایی مثل جاوا نیز، از دیزاین‌پترن‌ها استفاده شده‌است که نشان‌دهنده ی اهمیت و مفیدبودن استفاده از این الگوهای‌طراحی است.البته باید توجه کنیم که دیزاین پترن ها ادعا نمی کنند که راه حل پیشنهاد شده توسط آنها، تنها راه‌حل ممکن برای مسئله‌ی مشخص شده است! بلکه الگوهای‌طراحی، راه‌حل هایی را به ما نشان می‌دهند که در طی پروژه‌های مختلف ثابت شده است می‌توانند مسئله‌ی موردنظر را به شکل خوب و بهینه حل کنند. این الگوهای‌طراحی که قبلا بارها در آزمون و خطای برنامه‌نویسان مختلف، امتحان خود را پس داده‌اند، به صورتی طراحی شده اند که آنقدر واضح باشد تا به همه‌ی توسعه‌دهندگان در طراحی یک معماری خوب برای نرم‌افزار درحال توسعه کمک کنند. این موضوع در طراحی معماری سیستم بسیار کمک‌کننده است و به معماران نرم‌افزار کمک می‌کند تا بتوانند به وسیله‌ی آنها یک سیستم بهتر را طراحی کنند.دیزاین‌پترن ها به طور کلی به دو دسته تقسیم می‌شوند:1- Core Java (or JSE) Design Patterns2- JEE Design Patternsهر یک از این دسته‌ها نیز به تنهایی شامل تقسیم‌بندی‌های مختلفی هستند که در این بخش به بررسی آنها می‌پردازیم:دسته‌ی‌اول) Core Java (or JSE) Design Patternsاین دسته، شامل سه گروه از الگوهای‌طراحی به شکل زیر می باشد:اول) Creational Design Patternاین دسته از دیزاین‌پترن ها روی راههای ایجاد آبجکت از یک کلاس تمرکز دارند و زمانی استفاده می شوند که قراراست در هنگام ساخت Instance از یک کلاس، تصمیم خاصی گرفته شود یا شرایط خاصی رعایت شود.دوم) Structural Design Patternالگوهای‌طراحی ساختاری با این هدف ایجاد شده‌اند که مشخص کنند چطور می‌توانیم کلاس‌ها و آبجکت‌ها را باهم ترکیب کنیم و به این ترتیب یک ساختار بزرگتر ایجاد کنیم. این الگوها، این کار را با مشخص‌کردن ارتباطات بین کلاسها و ساده‌کردن ساختارها انجام می‌دهند.در واقع این الگوها روی این موضوع تمرکز می کنند که کلاسها باید چگونه و با چه ترتیبی از یکدیگر ارث ببرند یا با هم ترکیب شوند تا روابطی که میخواهیم ایجاد شود.سوم) Behavioral Design Patternالگوهای‌طراحی رفتاری به نحوه‌ی تعامل درست و پاسخگوبودن آبجکت‌ها مربوط می‌شود. در الگوهای‌طراحی موجود در این دسته، تعامل بین اشیاء باید به گونه ای باشد که بتوانند به راحتی با یکدیگر تعامل و همکاری کنند.دسته‌ی‌دوم) JEE Design Patternsالگوهای طراحی J2EE برای توسعه برنامه های کاربردی مبتنی بر وب طراحی شده است و شامل سه دسته ی زیر می باشند:Presentation Layer Design PatternBusiness Layer Design PatternIntegration Layer Design Patternدر بخش‌های بعد، الگوهای‌طراحی مربوط به هر دسته را به‌صورت دقیق توضیح خواهم داد. توصیه می‌کنم تا انتهای این سلسله پست‌ها با من همراه باشید.</description>
                <category>محدثه سالم</category>
                <author>محدثه سالم</author>
                <pubDate>Mon, 02 Aug 2021 19:27:59 +0430</pubDate>
            </item>
                    <item>
                <title>بهترین گوشی برای گیمینگ چه ویژگی هایی دارد؟</title>
                <link>https://virgool.io/GameWorld/best-gaming-smartphone-properties-ti0wbhzmmajr</link>
                <description>بازی های دیجیتال، از جمله تفریحات بسیار محبوبی به شمار می رود که طرفداران آن اصولا از رنج سنی مشخصی نیستند و در هر سن و از هر قشری طرفداران خاص خودش را دارد. اما برخی از افراد هستند که از بازی کردن لذت بیشتری میبرند و وقت و انرژی بیشتری برای آن می گذارند. از طرفی در دنیای امروز، شاید زمان و شرایط اینکه در خانه بنشینید و با استفاده از کامپیوتر و لپ تاپ و یا کنسول بازی، این کار را انجام دهید کمتر پیش می آید. به همین دلیل، خرید یک گوشی گیمینگ توانمند بهترین راه برای زدن هر دو هدف با یک تیر است. به این ترتیب هم میتوانید هر جایی که می خواهید بروید و هم از بازی کردنتان عقب نیفتید و آن را با خود به همراه داشته باشید تا در اولین فرصت ادامه دهید. در این مقاله به بررسی ویژگی های یک گوشی گیمینگ خوب می پردازیم. با ما همراه باشید.ویژگی های یک گوشی گیمینگ خوب چه چیزهایی هستند؟اگر گیم بازی کردن جزو مهمی از تفریحاتتان است و یا حتی اگر از گوشی تان زیاد استفاده می کنید و با آن کارهای سنگین تر از کارهای روزمره انجام می دهید، حتما باید در انتخاب گوشی ای که می خرید دقت کنید. چرا که با توجه به کار سنگینی که میخواهید بر عهده ی دستگاه تلفن هوشمندتان بگذارید، باید گوشی ای را انتخاب کنید که زورش به انجام تمام کارهای مورد نظر شما برسد. اگر بخواهیم به طور خلاصه ویژگی های گوشی های خوب برای گیمینگ و کارهای سنگین را بشمریم می توانیم به پنج ویژگی زیر اشاره کنیم:1- گرافیک قدرتمنداگر بخواهیم یک معرفی کلی و کوتاه درباره ی پردازنده ی گرافیکی موجود در گوشی های هوشمند داشته باشیم، میتوانیم بگوییم که  پردازنده گرافیکی موبایل یا GPU موبایل، یک پردازنده اختصاصی است که وظیفه ی تسریع عملکرد برنامه‌های گرافیکی، رابط کاربری و محتوای سه بعدی موجود در تلفن های هوشمند و تبلت‌ها را به عهده دارد. به عنوان نمونه از وظایف این پردازنده می توانیم به اجرای بازی‌های سه بعدی واقع گرایانه و رابط کاربری گرافیکی یا GUI اشاره کنیم. در نتیجه همان طور که از نام این پردازنده نیز مشخص است، وظیفه‌ی محاسبات گرافیکی بر عهده‌ی آن است. با توجه به رشد چشمگیر گرافیک بازی های ویدئویی و بخصوص بازی های موبایلی و اجرای سه بعدی محیط بازی، این موضوع خیلی اهمیت دارد که دستگاه تلفن همراه شما بتواند از نظر گرافیکی، به طور کامل بازی را اجرا کند و همچنین پردازش های مورد نظر را به خوبی انجام دهد تا درهنگام جا به جایی در محیط بازی مشکلی به وجود نیاورد.2- نمایشگر با نرخ تازه سازی بالا (refresh rate)همانطور که از نام این ویژگی پیداست، نرخ تازه‌سازی تصویر ، نشان دهنده ی میزان سرعت نمایشگر در تازه‌سازی تصاویر در هر ثانیه است. شاید اگر از گوشیتان استفاده ی خاصی نمیکنید و تنها در حد گشتن در صفحات وب یا شبکه های اجتماعی از آن استفاده می کنید، این موضوع به نظرتان چندان اهمیتی نداشته باشد؛ اما زمانی که بخواهید بازی های ویدئویی انجام دهید و یا از نتایج لحظه به لحظه ی  یک مسابقه ی ورزشی مهم و صحنه های حساس آن اطلاع پیدا کنید، متوجه اهمیت بالای این موضوع در بهبود کیفیت در هنگام استفاده از گوشی می شوید. واحد نرخ رفرش ریت هرتز (Hz) می باشد. البته این نرخ تنها مخصوص تلفن های هوشمند نیست و برای هر نمایشگری مانند تلویزیون و یا مانیتور به کار برده می شود .برای اینکه بتوانید صفحه نمایشگر با ویژگی های مورد نظرتان را پیدا کنید، باید بگوییم که معمولا هرچه نرخ تازه‌سازی تصویر بیشتر باشد، صفحه نمایش می تواند تجربه‌ی خوشایندتری را برایمان رقم بزند. دلیل آن هم واضح است. چون در صورت بالا بودن این نرخ، صفحه ‌نمایش در برابر تغییرات تصویر سریع تر واکنش نشان می دهد. اما چالشی که در این باره وجود دارد نیز این است که هر چقدر میزان رفرش‌ ریت بیشتر شود، طبیعتا قیمت تمام شده ی دستگاه نیز گران تر می شود و این مسئله ممکن است در انتخاب شما موثر باشد. همین علت باعث شده است که بسیاری از تولید کنندگان محصولات الکترونیکی، در هنگام افزایش نرخ رفرش ریت تصویر در دستگاه‌هایشان، احتیاط کنند و خیلی آن را بالا نبرند. مگر اینکه دلیل موجه و قانع‌کننده‌ای برای کارشان داشته باشند.البته باید به این نکته هم اشاره کنیم که نرخ رفرش ریت بیشتر، لزوما به ‌معنی نمایش بهتر تصاویر نیست. بلکه کیفیت نهایی تصاویر نمایش داده شده به عوامل زیادی بستگی دارد که نیاز است همه ی آن ها با هم و در کنار هم بررسی شود. همچنین کیفیت محتوای تماشا شده نیز نقش زیادی در کیفیت تصویر و همچنین رفرش‌ریت نمایشگر ایفا می‌کند. برای مثال می توان گفت که اگر فیلمی که با نرخ 60 فریم ‌بر ‌ثانیه پخش می‌شود را بر روی دو نمایشگر 60 و 120 هرتزی پخش کنیم، خواهیم دید که بدون درنظرگرفتن تفاوت‌های فنی دیگر، تجربه‌ی مشابهی روی آن دو نمایشگر ایجاد می کند.3- باتری قدرتمندتا این قسمت از مقاله، تا حدودی با تلاش زیادی که گوشی هوشمند در هنگام بازی برای ایجاد یک تجربه ی کاربری خوب و بی دردسر برای شما می کند، آشنا شدیم. اما نکته ای که وجود دارد این است که گوشی هوشمند شما قاعدتا برای انجام تمام این فعالیت ها به انرژی هم نیاز دارد تا بتواند از پس تمامی این وظایف بر بیاید. از طرفی ذات بازی از نوع سرگرمی است و بخصوص با معرفی بازی های جذاب جدید به بازار، زمانی که شروع به بازی میکنید تا ساعت ها درگیر جذابیتهای بازی می شوید و ممکن است محاسبه ی زمان از دستتان در برود. در این شرایط (بخصوص اگر جای حساس بازی بوده باشید) اگر باتری گوشیتان تمام شود، خستگی تمام مراحلی که گذراندید به همراه فشار عصبی به سمتتان هجوم می آورد و خاطره ی بدی را برایتان می سازد. به همین دلیل یکی از مهمترین ارکان گوشی های مخصوص گیمینگ باتری قدرتمند آنهاست که باید در حدی باشد که از پس تمام این سختی ها بر بیاید.4- چیپ ست قدرتمندهمانطور که قابل حدس است، بخاطر پردازش های سنگین گرافیکی و همچنین پردازش های کاربردی و صوتی- تصویری در کنار هزاران فعالیت دیگری که باید همزمان در پشت صحنه ی گوشی شما رخ دهد ، پردازنده یا چیپ ست قدرتمند نقش بسیار اساسی ای در گوشی های مناسب برای گیمینگ بازی می کنند.  برای گوشی هایی که با سیستم عامل اندروید ارائه می شوند، می توان گفت چیپست‌های اسنپ دراگون سری ۷۰۰ می‌توانند نقطه شروع مناسبی باشند. البته با اندکی اغماض م یتوانیم بگوییم به لحاظ فنی، حتی چیپ‌های اسنپ دراگون سری ۶۰۰ نیز می‌توانند فعالیت های مورد نیاز را انجام دهند اما ممکن است در اجرای بعضی عناوین با مشکلاتی مواجه شوند.به همین دلیل نمیتوان با خیال راحت آن را توصیه کرد. در میان گوشی های آیفون‌ نیز مدل‌هایی با چیپ A11 به بعد (آیفون ۸ به بعد) می‌توانند به خوبی و بدون نقص بسیاری از بازی ها را اجرا کنند. البته می توان گفت اگر بازی های خیلی خاصی انجام نمی دهید، حتی آیفون ۷ با چیپA10 نیز می تواند انتخاب خوبی برای شما باشد.5- امکانات اتصال به اینترنت پرسرعتاگر گیمر باشید، حتما میدانید که از مدتها پیش دنیای بازی های آفلاین برای گیمر های حرفه ای رو به اتمام است. در عصر حاضر، بازار بازی های آنلاین بسیار داغ است و گیمر ها حتی در برخی بازی ها در سطح جهانی با هم رقابت می کنند. اگر اهل این دست بازی ها باشید، حتما اهمیت بالای اینترنت و پشتیبانی از نسل های جدید و پرسرعت اینترنت را با تمام وجود حس کرده اید. گوشی هوشمندی که می خواهید از آن به عنوان گیمینگ هم استفاده کنید نیز باید بتواند از نسل های جدید و به روز انیترنت مانند نسل 5G و 4G نیز پشتیبانی کند و قدرتش به اندازه ای باشد که در صورت استفاده از اینترنت پرسرعت، بتواند فعاالیت های خود را نیز هندل کند و دچار مشکل نشود.نتیجه گیریاگر قصد خرید گوشی دارید و میدانید که میخواهید در کارهای سنگین مثل بازی یا استفاده از برنامه های سنگین و با پردازش های زیاد از آن استفاده کنید، بهتر است قبل از خرید، با دقت ویژگی های آن را بررسی کرده و سپس انتخاب کنید. شما می توانید با مقایسه ی گوشی های گیمینگ موجود در بازار، از نظر مشخصاتی که در این مقاله برای گوشی های گیمینگ شمردیم، به راحتی مناسبترین گوشی برای خودتان را پیدا کنید و آن را بخرید.امیدوارم این مقاله برای شما مفید بوده باشد.</description>
                <category>محدثه سالم</category>
                <author>محدثه سالم</author>
                <pubDate>Mon, 01 Feb 2021 12:37:29 +0330</pubDate>
            </item>
            </channel>
</rss>