در بسیاری از پروژه‌های نرم‌افزاری، وقتی صحبت از تست می‌شود، اولین چیزی که به ذهن می‌رسد بررسی ظاهر و عملکرد برنامه از طریق رابط کاربری (UI) است. اما آنچه کاربر در صفحه می‌بیند، تنها بخش کوچکی از اتفاقاتی است که در پشت صحنه رخ می‌دهد.

برای مثال، فرض کنید کاربر در یک فروشگاه اینترنتی سفارش خود را ثبت می‌کند. ممکن است صفحه با موفقیت پیام «سفارش با موفقیت ثبت شد» را نمایش دهد؛ اما آیا واقعاً اطلاعات سفارش در دیتابیس ذخیره شده است؟ آیا مبلغ سفارش درست ثبت شده؟ آیا شناسه کاربر و سفارش به‌درستی به یکدیگر مرتبط شده‌اند؟ اگر کاربر آدرس خود را تغییر دهد، آیا مقدار جدید در دیتابیس نیز به‌درستی به‌روزرسانی می‌شود؟

پاسخ این پرسش‌ها همیشه از طریق رابط کاربری مشخص نیست. اینجا تست دیتابیس اهمیت پیدا می‌کند.

تست دیتابیس به تستر کمک می‌کند داده‌هایی را که در پشت صحنه نرم‌افزار ایجاد، تغییر یا حذف می‌شوند بررسی کند و مطمئن شود اطلاعات مطابق نیازمندی‌های سیستم و قوانین کسب‌وکار در دیتابیس ذخیره و مدیریت می‌شوند.

تستر برای انجام این بررسی‌ها معمولاً به درک مناسبی از ساختار دیتابیس و زبان SQL نیاز دارد. البته هدف تستر این نیست که به یک متخصص طراحی یا مدیریت دیتابیس تبدیل شود؛ بلکه باید بتواند با استفاده از SQL، داده‌های موردنیاز را پیدا کند، صحت آن‌ها را بررسی کند و ارتباط بین عملکرد نرم‌افزار و داده‌های ذخیره‌شده را مورد ارزیابی قرار دهد.

در این مقاله ابتدا با مفهوم تست دیتابیس و اهمیت آن آشنا می‌شویم، سپس مفاهیم پایه و سناریوهای مهم آن را بررسی می‌کنیم و در ادامه، مهم‌ترین مفاهیم و دستورات SQL موردنیاز یک تستر را با مثال‌های عملی یاد می‌گیریم.

۱. تست دیتابیس چیست؟

تست دیتابیس فرایندی برای بررسی صحت، کامل بودن، یکپارچگی و عملکرد داده‌هایی است که توسط یک نرم‌افزار در دیتابیس ذخیره یا از آن بازیابی می‌شوند.

در واقع، تستر در تست دیتابیس فقط خود دیتابیس را به‌صورت مستقل بررسی نمی‌کند؛ بلکه می‌خواهد مطمئن شود نرم‌افزار و دیتابیس به‌درستی با یکدیگر کار می‌کنند.

برای مثال، فرض کنید کاربر در یک سامانه ثبت‌نام می‌کند. در ظاهر، ممکن است همه‌چیز درست به نظر برسد:

کاربر فرم ثبت‌نام را تکمیل می‌کند
             ↓
      روی Register کلیک می‌کند
             ↓
       پیام موفقیت نمایش داده می‌شود

اما تستر باید بتواند بررسی کند که در پشت صحنه نیز اتفاق مورد انتظار رخ داده است:

Register
   ↓
Application / API
   ↓
Database
   ↓
ایجاد رکورد جدید در جدول Users

در اینجا می‌توان بررسی کرد:

  • آیا رکورد کاربر واقعاً ایجاد شده است؟
  • آیا نام و ایمیل درست ذخیره شده‌اند؟
  • آیا نوع و فرمت داده‌ها صحیح است؟
  • آیا برای کاربر یک شناسه یکتا ایجاد شده است؟
  • آیا مقدارهای اجباری خالی نمانده‌اند؟
  • آیا رکورد تکراری ایجاد نشده است؟
  • آیا ارتباط کاربر با سایر داده‌ها به‌درستی برقرار شده است؟

بنابراین، تست دیتابیس را می‌توان بخشی از فرایند اعتبارسنجی نرم‌افزار دانست که روی داده‌ها و نحوه تعامل نرم‌افزار با آن‌ها تمرکز دارد.

تست دیتابیس فقط بررسی وجود داده نیست

یکی از اشتباهات رایج این است که تصور کنیم اگر رکورد موردنظر در دیتابیس وجود داشته باشد، پس تست با موفقیت انجام شده است.

در حالی که تستر باید محتوای داده و ارتباط آن با سایر داده‌ها را نیز بررسی کند.

برای مثال، فرض کنید یک سفارش با مبلغ ۵۰۰ هزار تومان ثبت شده است. وجود یک رکورد در جدول Orders به‌تنهایی کافی نیست. باید بررسی شود که:

  • مبلغ سفارش درست ذخیره شده باشد.
  • شناسه مشتری صحیح باشد.
  • وضعیت سفارش مقدار مورد انتظار را داشته باشد.
  • تاریخ ثبت سفارش درست باشد.
  • اقلام سفارش به همان سفارش متصل باشند.
  • اطلاعات ذخیره‌شده با اطلاعاتی که کاربر در UI یا API ارسال کرده مطابقت داشته باشد.

به همین دلیل، تست دیتابیس ارتباط نزدیکی با تست عملکردی، تست API و تست رابط کاربری دارد و می‌تواند به تستر کمک کند خطاهایی را پیدا کند که از طریق UI به‌سادگی قابل مشاهده نیستند.

۲. چرا تستر باید دیتابیس را تست کند؟

ممکن است این سؤال مطرح شود که اگر تستر عملکرد نرم‌افزار را از طریق UI و API بررسی می‌کند، چرا باید سراغ دیتابیس برود؟

دلیل اصلی این است که موفقیت یک عملیات در ظاهر نرم‌افزار لزوماً به معنی درست بودن داده‌های پشت آن نیست.

فرض کنید در یک فروشگاه اینترنتی، کاربر آدرس خود را تغییر می‌دهد. سیستم پیام زیر را نمایش می‌دهد:

آدرس شما با موفقیت تغییر کرد.

اما ممکن است در پشت صحنه یکی از این مشکلات رخ داده باشد:

  • آدرس جدید اصلاً در دیتابیس ذخیره نشده باشد.
  • آدرس در رکورد اشتباه ذخیره شده باشد.
  • بخشی از اطلاعات آدرس از بین رفته باشد.
  • مقدار قبلی به‌اشتباه باقی مانده باشد.
  • اطلاعات آدرس در جدول مرتبط به‌درستی به کاربر متصل نشده باشد.

اگر تستر فقط UI را بررسی کند، ممکن است این خطاها را نبیند.

بررسی صحت داده‌ها

یکی از مهم‌ترین دلایل تست دیتابیس، اطمینان از صحت داده‌ها (Data Accuracy) است.

مثلاً اگر کاربر مبلغ ۲۵۰ هزار تومان پرداخت کرده باشد، باید مطمئن شویم همین مقدار در دیتابیس ثبت شده است، نه ۲۵ هزار تومان یا مقدار دیگری.

بررسی کامل بودن داده‌ها

گاهی داده ایجاد می‌شود، اما همه اطلاعات موردنیاز ذخیره نمی‌شوند.

برای مثال، هنگام ثبت سفارش ممکن است اطلاعاتی مانند موارد زیر موردنیاز باشند:

  • شناسه کاربر
  • شماره سفارش
  • مبلغ
  • وضعیت سفارش
  • تاریخ ثبت
  • اقلام سفارش

تستر باید بررسی کند که داده‌های موردنیاز مطابق نیازمندی سیستم و به‌صورت کامل ذخیره شده‌اند.

بررسی ارتباط بین داده‌ها

داده‌های یک نرم‌افزار معمولاً در چند جدول مختلف قرار دارند و بین آن‌ها ارتباط وجود دارد.

Users
  │
  │ user_id
  ↓
Orders
  │
  │ order_id
  ↓
Order Items

ممکن است سفارش در جدول Orders ایجاد شده باشد، اما به کاربر اشتباه متصل شده باشد. چنین خطایی شاید در بعضی شرایط از طریق UI قابل تشخیص نباشد.

بررسی نتیجه عملیات‌های مختلف

تستر می‌تواند بررسی کند که عملیات‌هایی مانند موارد زیر واقعاً همان نتیجه‌ای را ایجاد می‌کنند که انتظار می‌رود:

  • ایجاد (Create)
  • خواندن (Read)
  • ویرایش (Update)
  • حذف (Delete)

برای مثال، اگر کاربر یک حساب کاربری را حذف کند، تستر می‌تواند بررسی کند که آیا رکورد مربوط به کاربر حذف شده و داده‌های وابسته نیز مطابق قوانین سیستم مدیریت شده‌اند یا خیر.

پیدا کردن خطاهایی که در UI دیده نمی‌شوند

یکی از مهم‌ترین مزایای تست دیتابیس این است که به تستر اجازه می‌دهد یک لایه عمیق‌تر از نرم‌افزار را بررسی کند.

به همین دلیل، تست دیتابیس صرفاً یک مهارت جانبی برای تستر نیست؛ بلکه در بسیاری از پروژه‌ها ابزاری مهم برای اطمینان از صحت عملکرد سیستم و داده‌های آن است.

در ادامه، قبل از اینکه سراغ دستورات SQL برویم، بهتر است با مفاهیم پایه دیتابیس که یک تستر باید بشناسد آشنا شویم.

۳. مفاهیم پایه دیتابیس که یک تستر باید بداند

برای انجام تست دیتابیس، لازم نیست تستر متخصص طراحی یا مدیریت دیتابیس باشد. اما باید با تعدادی از مفاهیم پایه آشنا باشد تا بتواند ساختار داده‌ها را درک کند و نتایج تست خود را به‌درستی بررسی کند.

در ادامه مهم‌ترین مفاهیمی را که یک تستر باید بشناسد مرور می‌کنیم.

Database

Database یا دیتابیس محلی برای ذخیره و مدیریت داده‌های یک نرم‌افزار است.

برای مثال، یک فروشگاه اینترنتی ممکن است اطلاعات زیر را در دیتابیس خود نگهداری کند:

  • کاربران
  • محصولات
  • سفارش‌ها
  • پرداخت‌ها
  • آدرس‌ها

این اطلاعات معمولاً در جدول‌های مختلف سازمان‌دهی می‌شوند.

Table

Table یا جدول محلی است که داده‌های مرتبط در آن ذخیره می‌شوند.

idnameemailstatus
1Aliali@example.comactive
2Sarasara@example.comactive
3Rezareza@example.cominactive

در این مثال، هر کاربر یک Row و هر ویژگی کاربر یک Column محسوب می‌شود.

Row

Row یا سطر، یک رکورد از داده‌هاست.

1 | Ali | ali@example.com | active

این سطر اطلاعات مربوط به یک کاربر را نشان می‌دهد.

در تست دیتابیس، معمولاً بررسی می‌کنیم که آیا رکورد مورد انتظار ایجاد، تغییر یا حذف شده است.

Column

Column یا ستون، یک ویژگی مشخص از داده‌ها را نگهداری می‌کند.

id
name
email
status

هر ستون معمولاً دارای یک Data Type نیز هست؛ برای مثال:

  • INTEGER
  • VARCHAR
  • DATE
  • BOOLEAN

تستر باید بتواند بررسی کند که داده ذخیره‌شده با نوع و محدودیت تعریف‌شده برای آن ستون سازگار است.

Primary Key

Primary Key شناسه‌ای است که هر رکورد را به‌صورت یکتا مشخص می‌کند.

id
---
1
2
3

اگر id به‌عنوان Primary Key تعریف شده باشد، دو کاربر نباید یک id یکسان داشته باشند.

از دید تستر، مواردی مانند Unique بودن شناسه، عدم ایجاد مقدار تکراری و ایجاد صحیح شناسه برای رکورد جدید اهمیت دارند.

Foreign Key

Foreign Key برای ایجاد ارتباط بین جدول‌ها استفاده می‌شود.

برای مثال، فرض کنیم هر سفارش متعلق به یک کاربر است:

Users
----------------
id
name

Orders
----------------
id
user_id
amount

در اینجا Orders.user_id می‌تواند به Users.id اشاره کند.

این ارتباط به تستر کمک می‌کند بررسی کند که مثلاً سفارش یک کاربر به کاربر دیگری نسبت داده نشده باشد.

Constraint

Constraint یا محدودیت، قوانینی است که برای کنترل صحت داده‌ها در دیتابیس تعریف می‌شود.

از نمونه‌های مهم آن می‌توان به موارد زیر اشاره کرد:

  • PRIMARY KEY
  • FOREIGN KEY
  • UNIQUE
  • NOT NULL
  • DEFAULT
  • CHECK

برای تستر، شناخت این محدودیت‌ها مهم است؛ زیرا بسیاری از قوانین مربوط به اعتبار داده‌ها در همین سطح اعمال می‌شوند.

NULL

NULL به معنی نبودن مقدار است و نباید آن را با مقدار خالی ('') یا صفر (0) یکی دانست.

مثلاً ممکن است ستون phone_number برای بعضی کاربران مقدار NULL داشته باشد؛ یعنی شماره تلفنی برای آن رکورد ثبت نشده است.

این موضوع در تست دیتابیس اهمیت زیادی دارد و حتی هنگام نوشتن Queryهای SQL باید روش صحیح بررسی NULL را بدانیم.

Relationship

جدول‌های یک دیتابیس معمولاً مستقل از یکدیگر نیستند و با هم ارتباط دارند.

رابطه‌های رایج عبارت‌اند از:

  • One-to-One
  • One-to-Many
  • Many-to-Many

برای مثال، یک کاربر می‌تواند چندین سفارش داشته باشد:

User
  │
  ├── Order 1
  ├── Order 2
  └── Order 3

درک این ارتباط‌ها برای تستر بسیار مهم است؛ چون بسیاری از خطاهای داده‌ای در همین روابط بین جدول‌ها اتفاق می‌افتند.

در این مرحله لازم نیست همه جزئیات فنی دیتابیس را یاد بگیریم. هدف این است که وقتی در ادامه یک Query مانند SELECT یا JOIN می‌بینیم، بدانیم دقیقاً چه داده‌ای را از چه ساختاری و با چه رابطه‌ای داریم بررسی می‌کنیم.

در بخش بعدی وارد SQL و مهم‌ترین دستوراتی می‌شویم که یک تستر برای تست دیتابیس به آن‌ها نیاز دارد.

۴. SQL چیست و چرا تستر به آن نیاز دارد؟

SQL مخفف Structured Query Language است و زبانی است که برای کار با داده‌های موجود در بسیاری از دیتابیس‌های رابطه‌ای استفاده می‌شود.

تستر معمولاً از SQL برای کارهایی مانند موارد زیر استفاده می‌کند:

  • پیدا کردن داده‌های موردنظر
  • بررسی صحت داده‌های ذخیره‌شده
  • شمارش رکوردها
  • مقایسه داده‌ها
  • بررسی ارتباط بین جدول‌ها
  • ایجاد یا آماده‌سازی داده‌های تست
  • تغییر داده‌ها در محیط تست
  • حذف داده‌های تست
  • بررسی نتیجه عملیات API یا UI در دیتابیس

برای مثال، فرض کنید کاربر جدیدی در سیستم ثبت‌نام کرده است. تستر می‌تواند با یک Query ساده بررسی کند که آیا این کاربر واقعاً در دیتابیس ایجاد شده است:

SELECT *
FROM users
WHERE email = 'ali@example.com';

اگر رکورد موردنظر برگردانده شود، تستر می‌تواند اطلاعات ذخیره‌شده را با اطلاعاتی که کاربر در فرم ثبت‌نام وارد کرده یا API ارسال کرده مقایسه کند.

آیا تستر باید SQL را حرفه‌ای بداند؟

خیر.

تستر برای شروع کار نیازی ندارد به یک متخصص SQL یا Database Developer تبدیل شود. چیزی که اهمیت دارد این است که بتواند Queryهای موردنیاز برای بررسی داده‌ها را بنویسد و نتیجه آن‌ها را تفسیر کند.

دستور / مفهومکاربرد برای تستر
SELECTخواندن و بررسی داده‌ها
WHEREپیدا کردن رکوردهای خاص
AND / ORترکیب شرایط جست‌وجو
ORDER BYمرتب‌سازی نتایج
LIKEجست‌وجوی الگو در داده‌ها
INبررسی چند مقدار
BETWEENبررسی یک بازه
COUNTشمارش رکوردها
DISTINCTپیدا کردن مقادیر غیرتکراری
JOINبررسی ارتباط بین جدول‌ها
GROUP BYگروه‌بندی داده‌ها
HAVINGفیلتر کردن گروه‌ها
INSERTایجاد داده
UPDATEتغییر داده
DELETEحذف داده

البته همه این دستورات را قرار نیست صرفاً به‌صورت تئوری یاد بگیریم. بهتر است هرکدام را در قالب یک سناریوی واقعی تست بررسی کنیم.

برای مثال، به جای اینکه فقط بدانیم COUNT برای شمارش رکوردها استفاده می‌شود، می‌توانیم یک سناریوی تست داشته باشیم:

قبل از ثبت‌نام کاربر ۱۰ رکورد در جدول Users وجود دارد. پس از ثبت‌نام موفق یک کاربر جدید، انتظار داریم تعداد رکوردها به ۱۱ برسد.

SELECT COUNT(*)
FROM users;

به این شکل، SQL از یک موضوع صرفاً برنامه‌نویسی به ابزار عملی برای تست نرم‌افزار تبدیل می‌شود.

نکته مهم: اجرای INSERT، UPDATE و DELETE روی دیتابیس واقعی می‌تواند خطرناک باشد. تستر باید این عملیات را در محیط مناسب تست انجام دهد و قبل از اجرای Queryهای تغییردهنده، تأثیر آن‌ها را به‌دقت بررسی کند.

در ادامه، از ساده‌ترین و پرکاربردترین دستور شروع می‌کنیم: SELECT؛ دستوری که بخش بزرگی از کارهای روزمره تستر هنگام بررسی دیتابیس با آن انجام می‌شود.

۵. دستور SELECT؛ مهم‌ترین ابزار تستر برای خواندن داده‌ها

یکی از مهم‌ترین دستورات SQL برای تستر، SELECT است. با استفاده از SELECT می‌توانیم داده‌های موجود در یک یا چند جدول را بخوانیم و بررسی کنیم.

در تست دیتابیس، بخش زیادی از کار ما شامل خواندن و بررسی داده‌ها بدون تغییر دادن آن‌ها است؛ بنابراین یادگیری SELECT اهمیت زیادی دارد.

ساده‌ترین حالت SELECT

فرض کنیم جدولی با نام users داریم. برای مشاهده تمام اطلاعات آن می‌توانیم بنویسیم:

SELECT *
FROM users;

علامت * به معنی انتخاب تمام ستون‌هاست.

اگر جدول users شامل ستون‌های زیر باشد:

id
name
email
status

Query بالا تمام ستون‌ها و رکوردهای جدول را برمی‌گرداند.

انتخاب ستون‌های مشخص

معمولاً بهتر است فقط ستون‌هایی را که برای تست نیاز داریم انتخاب کنیم:

SELECT id, name, email
FROM users;

در این حالت فقط سه ستون id، name و email نمایش داده می‌شوند.

این روش مخصوصاً زمانی مفید است که جدول ستون‌های زیادی داشته باشد و ما فقط به چند مورد خاص نیاز داشته باشیم.

استفاده از SELECT برای بررسی نتیجه یک تست

فرض کنید در یک سامانه، کاربر جدیدی با ایمیل زیر ثبت شده است:

ali@example.com

تستر می‌تواند با Query زیر بررسی کند که آیا رکورد مربوط به این کاربر در دیتابیس ایجاد شده است:

SELECT id, name, email, status
FROM users
WHERE email = 'ali@example.com';

در اینجا SELECT داده را می‌خواند و WHERE مشخص می‌کند که فقط رکورد مربوط به این ایمیل را می‌خواهیم.

مثلاً نتیجه می‌تواند چیزی شبیه این باشد:

idnameemailstatus
25Aliali@example.comactive

حالا تستر می‌تواند این اطلاعات را با داده‌های مورد انتظار مقایسه کند.

چرا بهتر است همیشه از SELECT * استفاده نکنیم؟

اگرچه استفاده از * ساده و سریع است، اما در Queryهای واقعی بهتر است تا حد امکان ستون‌های موردنیاز را مشخص کنیم.

به جای:

SELECT *
FROM users;

می‌توان نوشت:

SELECT id, email, status
FROM users;

این کار باعث می‌شود نتیجه Query خواناتر باشد و دقیقاً مشخص شود که تستر چه اطلاعاتی را بررسی می‌کند.

SELECT و بررسی داده‌های تست

یکی از کاربردهای مهم SELECT این است که تستر بتواند قبل و بعد از انجام یک عملیات، وضعیت دیتابیس را بررسی کند.

برای مثال، قبل از ثبت سفارش:

SELECT COUNT(*)
FROM orders;

فرض کنیم نتیجه 150 باشد.

حالا یک سفارش جدید ثبت می‌کنیم و Query را دوباره اجرا می‌کنیم:

SELECT COUNT(*)
FROM orders;

اگر نتیجه 151 باشد، یکی از موارد مورد انتظار ما تأیید شده است: یک رکورد جدید در جدول سفارش‌ها ایجاد شده است.

البته این به‌تنهایی کافی نیست و باید محتوای رکورد جدید و ارتباط آن با کاربر و اقلام سفارش را نیز بررسی کنیم.

یک نکته مهم برای تستر

SELECT معمولاً یک عملیات خواندن است و داده‌های دیتابیس را تغییر نمی‌دهد. به همین دلیل، تستر در بسیاری از بررسی‌های روزمره خود می‌تواند از آن برای مشاهده و اعتبارسنجی داده‌ها استفاده کند.

اما حتی در استفاده از SELECT نیز باید بدانیم دقیقاً چه داده‌ای را می‌خواهیم بررسی کنیم. اینجا دستور WHERE اهمیت پیدا می‌کند؛ چون به ما اجازه می‌دهد به جای بررسی تمام داده‌ها، رکوردهای موردنظر را پیدا کنیم.

۶. دستور WHERE؛ پیدا کردن داده موردنظر

در بسیاری از تست‌های دیتابیس، نمی‌خواهیم تمام رکوردهای یک جدول را مشاهده کنیم. معمولاً به دنبال یک رکورد یا مجموعه مشخصی از رکوردها هستیم.

برای این کار از WHERE استفاده می‌کنیم.

SELECT column_name
FROM table_name
WHERE condition;

یک مثال ساده

فرض کنیم می‌خواهیم کاربری با شناسه 25 را پیدا کنیم:

SELECT *
FROM users
WHERE id = 25;

در این حالت فقط رکوردی نمایش داده می‌شود که مقدار id آن برابر با 25 باشد.

استفاده از WHERE برای اعتبارسنجی داده

فرض کنید کاربر با ایمیل ali@example.com در سیستم ثبت‌نام کرده است.

می‌توانیم بررسی کنیم که این کاربر در دیتابیس وجود دارد یا خیر:

SELECT id, name, email
FROM users
WHERE email = 'ali@example.com';

اگر یک رکورد برگردانده شود، می‌توانیم اطلاعات آن را با داده مورد انتظار مقایسه کنیم.

این یکی از کاربردهای بسیار رایج WHERE در تست دیتابیس است.

عملگرهای مقایسه در WHERE

برای نوشتن شرط‌ها می‌توان از عملگرهای مختلف استفاده کرد:

عملگرمفهوم
=برابر است با
<>نابرابر است با
>بزرگ‌تر از
<کوچک‌تر از
>=بزرگ‌تر یا مساوی
<=کوچک‌تر یا مساوی

برای مثال، اگر بخواهیم سفارش‌هایی با مبلغ بیشتر از یک میلیون تومان را پیدا کنیم:

SELECT *
FROM orders
WHERE amount > 1000000;

یا سفارش‌هایی که مبلغ آن‌ها حداقل یک میلیون تومان است:

SELECT *
FROM orders
WHERE amount >= 1000000;

ترکیب چند شرط با AND

گاهی یک شرط کافی نیست.

فرض کنید می‌خواهیم کاربران فعال را پیدا کنیم که ایمیل آن‌ها متعلق به دامنه gmail.com است:

SELECT *
FROM users
WHERE status = 'active'
AND email LIKE '%gmail.com';

در اینجا هر دو شرط باید برقرار باشند.

این موضوع برای تستر بسیار کاربردی است؛ مثلاً زمانی که می‌خواهیم فقط داده‌هایی را بررسی کنیم که چند ویژگی مشخص دارند.

استفاده از OR

با OR کافی است حداقل یکی از شرط‌ها برقرار باشد.

مثلاً می‌خواهیم سفارش‌هایی را پیدا کنیم که وضعیت آن‌ها pending یا processing است:

SELECT *
FROM orders
WHERE status = 'pending'
OR status = 'processing';

ترکیب AND و OR

در Queryهای واقعی ممکن است چند شرط با هم ترکیب شوند.

SELECT *
FROM orders
WHERE status = 'paid'
AND (amount > 1000000 OR priority = 'high');

یعنی سفارش باید:

  1. وضعیت paid داشته باشد.
  2. و در عین حال یا مبلغ آن بیشتر از یک میلیون باشد، یا اولویت آن high باشد.

استفاده از پرانتز در چنین Queryهایی اهمیت زیادی دارد؛ چون ترتیب بررسی شرط‌ها می‌تواند روی نتیجه تأثیر بگذارد.

یک سناریوی واقعی برای تستر

فرض کنید Requirement سیستم می‌گوید:

فقط کاربران فعال می‌توانند سفارش جدید ثبت کنند.

پس از ثبت یک سفارش، تستر می‌تواند ابتدا کاربر مربوط به سفارش را پیدا کند:

SELECT id, status
FROM users
WHERE id = 25;

اگر نتیجه نشان دهد:

id = 25
status = active

سپس می‌توان سفارش‌های این کاربر را بررسی کرد:

SELECT *
FROM orders
WHERE user_id = 25;

به این ترتیب، تستر از SQL برای بررسی ارتباط بین Requirement، رفتار نرم‌افزار و داده‌های دیتابیس استفاده می‌کند.

این دقیقاً همان رویکردی است که می‌خواهیم در یادگیری SQL برای تستر دنبال کنیم: هر Query باید یک کاربرد واقعی در فرایند تست داشته باشد.

۷. مرتب‌سازی داده‌ها با ORDER BY

گاهی پیدا کردن رکوردهای موردنظر کافی نیست و لازم است داده‌ها را با ترتیب مشخصی مشاهده کنیم. برای مثال، ممکن است بخواهیم جدیدترین سفارش‌ها، بیشترین مبالغ یا آخرین کاربران ثبت‌نام‌شده را بررسی کنیم.

برای مرتب‌سازی نتایج یک Query از ORDER BY استفاده می‌کنیم.

SELECT column_name
FROM table_name
ORDER BY column_name;

مرتب‌سازی صعودی

به‌صورت پیش‌فرض، ORDER BY داده‌ها را به شکل صعودی مرتب می‌کند. برای مشخص کردن این موضوع می‌توان از ASC استفاده کرد:

SELECT *
FROM users
ORDER BY id ASC;

در این حالت کاربران بر اساس id از کوچک به بزرگ نمایش داده می‌شوند.

برای داده‌های متنی نیز مرتب‌سازی می‌تواند به ترتیب الفبایی انجام شود:

SELECT name, email
FROM users
ORDER BY name ASC;

مرتب‌سازی نزولی

با DESC می‌توان داده‌ها را از بزرگ به کوچک مرتب کرد:

SELECT *
FROM users
ORDER BY id DESC;

این روش برای تستر بسیار کاربردی است؛ مثلاً اگر بخواهیم جدیدترین رکوردها را بررسی کنیم:

SELECT id, name, created_at
FROM users
ORDER BY created_at DESC;

در اینجا رکوردهایی که تاریخ ایجاد جدیدتری دارند، در ابتدای نتیجه قرار می‌گیرند.

یک مثال کاربردی در تست سفارش

فرض کنید بعد از انجام یک تست، چند سفارش جدید ایجاد شده و می‌خواهیم جدیدترین سفارش‌ها را بررسی کنیم:

SELECT id, user_id, amount, status, created_at
FROM orders
ORDER BY created_at DESC;

حالا تستر می‌تواند سریع‌تر رکوردهای مربوط به عملیات اخیر را پیدا کند و بررسی کند که:

  • آیا سفارش ایجاد شده است؟
  • چه زمانی ایجاد شده است؟
  • متعلق به کدام کاربر است؟
  • مبلغ آن چقدر است؟
  • وضعیت آن چیست؟

مرتب‌سازی با چند ستون

گاهی لازم است داده‌ها بر اساس بیش از یک ستون مرتب شوند.

مثلاً می‌خواهیم سفارش‌ها ابتدا بر اساس وضعیت و سپس بر اساس مبلغ مرتب شوند:

SELECT id, status, amount
FROM orders
ORDER BY status ASC, amount DESC;

در این حالت ابتدا status معیار اصلی مرتب‌سازی است و اگر چند رکورد وضعیت یکسانی داشته باشند، مبلغ آن‌ها به‌صورت نزولی مرتب می‌شود.

چرا ORDER BY برای تستر مهم است؟

در دیتابیس‌های واقعی ممکن است هزاران یا میلیون‌ها رکورد وجود داشته باشد. بررسی همه آن‌ها معمولاً منطقی نیست.

با استفاده از WHERE و ORDER BY می‌توانیم داده‌های موردنظر را پیدا و مرتب کنیم.

SELECT id, email, created_at
FROM users
WHERE status = 'active'
ORDER BY created_at DESC;

این Query فقط کاربران فعال را پیدا می‌کند و آن‌ها را از جدیدترین به قدیمی‌ترین مرتب می‌کند.

ترکیب دستورهایی مانند SELECT، WHERE و ORDER BY یکی از پایه‌های اصلی Queryنویسی برای تستر است.

۸. جست‌وجوی الگو با LIKE

گاهی برای تست دیتابیس مقدار دقیق یک داده را نمی‌دانیم یا می‌خواهیم رکوردهایی را پیدا کنیم که بخشی از یک مقدار مشخص را در خود دارند.

برای چنین شرایطی از LIKE استفاده می‌کنیم.

مثلاً فرض کنید می‌خواهیم تمام کاربرانی را پیدا کنیم که ایمیل آن‌ها با gmail.com تمام می‌شود:

SELECT id, name, email
FROM users
WHERE email LIKE '%gmail.com';

در این Query، علامت % به این معنی است که قبل از gmail.com می‌تواند هر تعداد کاراکتر وجود داشته باشد.

کاربردهای مهم %

اگر بنویسیم:

WHERE name LIKE 'Ali%'

یعنی مقدار name باید با Ali شروع شود.

مثلاً:

  • Ali
  • Ali Reza
  • Ali Ahmad

اما Reza Ali در نتیجه قرار نمی‌گیرد.

اگر بنویسیم:

WHERE name LIKE '%Ali'

یعنی مقدار باید با Ali تمام شود.

و اگر بنویسیم:

WHERE name LIKE '%Ali%'

یعنی Ali می‌تواند هرجای مقدار قرار داشته باشد.

مثلاً:

  • Ali
  • Ali Reza
  • Reza Ali
  • Mohammad Ali

استفاده از LIKE در تست

فرض کنید Requirement سیستم می‌گوید:

ایمیل کاربران باید با دامنه شرکت example.com باشد.

تستر می‌تواند برای پیدا کردن داده‌هایی که با این دامنه مطابقت دارند از Query زیر استفاده کند:

SELECT id, email
FROM users
WHERE email LIKE '%@example.com';

یا اگر بخواهیم داده‌هایی را پیدا کنیم که با این دامنه مطابقت ندارند:

SELECT id, email
FROM users
WHERE email NOT LIKE '%@example.com';

این Query می‌تواند برای پیدا کردن داده‌های مشکوک یا ناسازگار با Requirement مفید باشد.

یک مثال دیگر

فرض کنید می‌خواهیم سفارش‌هایی را پیدا کنیم که شماره سفارش آن‌ها با ORD-2026 شروع می‌شود:

SELECT *
FROM orders
WHERE order_number LIKE 'ORD-2026%';

این روش مخصوصاً هنگام بررسی Test Data و پیدا کردن مجموعه‌ای از رکوردهای مرتبط با یک الگوی مشخص کاربرد دارد.

تفاوت LIKE و =

یک نکته مهم این است که = معمولاً برای مقایسه یک مقدار مشخص استفاده می‌شود:

WHERE email = 'ali@example.com'

در حالی که LIKE برای جست‌وجوی الگو مناسب است:

WHERE email LIKE '%@example.com'

در مثال اول فقط همان ایمیل مشخص پیدا می‌شود؛ اما در مثال دوم تمام ایمیل‌هایی که با @example.com تمام می‌شوند می‌توانند در نتیجه قرار بگیرند.

۹. استفاده از IN و BETWEEN برای بررسی چند مقدار و بازه‌ها

در تست دیتابیس، گاهی لازم است داده‌هایی را بررسی کنیم که یک مقدار مشخص ندارند، بلکه باید چند مقدار مختلف یا یک بازه مشخص را پیدا کنیم.

دو دستور پرکاربرد برای این کار IN و BETWEEN هستند.

دستور IN

فرض کنید می‌خواهیم سفارش‌هایی را پیدا کنیم که وضعیت آن‌ها یکی از موارد زیر باشد:

  • pending
  • processing
  • shipped

می‌توانیم به جای نوشتن چند شرط OR از IN استفاده کنیم:

SELECT id, status
FROM orders
WHERE status IN ('pending', 'processing', 'shipped');

این Query تمام سفارش‌هایی را برمی‌گرداند که وضعیت آن‌ها یکی از سه مقدار مشخص‌شده باشد.

همین Query را می‌توان با OR نیز نوشت:

SELECT id, status
FROM orders
WHERE status = 'pending'
   OR status = 'processing'
   OR status = 'shipped';

هر دو Query نتیجه مشابهی دارند، اما IN در چنین شرایطی معمولاً خواناتر و ساده‌تر است.

استفاده از NOT IN

اگر بخواهیم رکوردهایی را پیدا کنیم که مقدار مشخص‌شده را ندارند، می‌توانیم از NOT IN استفاده کنیم.

SELECT id, status
FROM orders
WHERE status NOT IN ('cancelled', 'deleted');

این Query سفارش‌هایی را برمی‌گرداند که وضعیت آن‌ها cancelled یا deleted نیست.

این قابلیت می‌تواند در تست داده‌ها برای پیدا کردن رکوردهایی که نباید در یک وضعیت خاص باشند مفید باشد.

دستور BETWEEN

BETWEEN برای بررسی قرار گرفتن یک مقدار در یک بازه استفاده می‌شود.

مثلاً اگر بخواهیم سفارش‌هایی را پیدا کنیم که مبلغ آن‌ها بین ۵۰۰ هزار تا یک میلیون تومان است:

SELECT id, amount
FROM orders
WHERE amount BETWEEN 500000 AND 1000000;

در حالت معمول، دو مقدار ابتدا و انتهای بازه نیز در نتیجه در نظر گرفته می‌شوند.

یعنی سفارش‌هایی با مبلغ زیر می‌توانند در نتیجه قرار بگیرند:

  • 500000
  • 750000
  • 1000000

استفاده از BETWEEN برای تاریخ

BETWEEN فقط برای اعداد نیست و می‌توان از آن برای بررسی تاریخ‌ها نیز استفاده کرد.

SELECT id, created_at
FROM orders
WHERE created_at BETWEEN '2026-09-01' AND '2026-09-14';

این Query برای پیدا کردن سفارش‌هایی در یک بازه زمانی استفاده می‌شود.

البته در Queryهای مربوط به تاریخ و زمان باید به نوع داده و وجود بخش ساعت نیز توجه کرد؛ زیرا در بعضی دیتابیس‌ها استفاده از BETWEEN روی یک بازه زمانی می‌تواند نتایج غیرمنتظره‌ای ایجاد کند.

یک سناریوی واقعی برای تستر

فرض کنید Requirement سیستم می‌گوید:

سفارش‌هایی با مبلغ بین ۱۰۰ هزار تا ۵۰۰ هزار تومان باید در دسته سفارش‌های معمولی قرار بگیرند.

تستر می‌تواند داده‌های موجود را بررسی کند:

SELECT id, amount, status
FROM orders
WHERE amount BETWEEN 100000 AND 500000;

سپس بررسی کند که وضعیت این سفارش‌ها مطابق Requirement است.

یا اگر بخواهیم سفارش‌هایی را پیدا کنیم که وضعیت آن‌ها یکی از وضعیت‌های مورد انتظار است:

SELECT id, amount, status
FROM orders
WHERE status IN ('pending', 'processing', 'completed');

به این ترتیب، IN و BETWEEN به تستر کمک می‌کنند به‌جای بررسی تک‌تک رکوردها، مجموعه‌ای از داده‌های مرتبط با یک سناریوی تست را سریع‌تر پیدا کند.

۱۰. شمارش رکوردها با COUNT

یکی از کاربردهای بسیار مهم SQL در تست دیتابیس، شمارش تعداد رکوردها است. برای این کار از تابع COUNT استفاده می‌کنیم.

این قابلیت برای تستر اهمیت زیادی دارد؛ چون در بسیاری از سناریوها لازم است بدانیم بعد از انجام یک عملیات، تعداد داده‌ها تغییر کرده است یا خیر.

ساده‌ترین حالت COUNT

برای شمارش تمام رکوردهای یک جدول:

SELECT COUNT(*)
FROM users;

فرض کنید نتیجه این Query برابر با 100 باشد. یعنی در جدول users صد رکورد وجود دارد.

استفاده از COUNT همراه با WHERE

می‌توانیم فقط رکوردهایی را که یک شرط خاص دارند شمارش کنیم.

SELECT COUNT(*)
FROM users
WHERE status = 'active';

یا تعداد سفارش‌های تکمیل‌شده:

SELECT COUNT(*)
FROM orders
WHERE status = 'completed';

این قابلیت در تست سناریوهای مختلف بسیار مفید است.

استفاده از COUNT برای بررسی ایجاد رکورد

فرض کنید قبل از ثبت یک کاربر جدید، تعداد کاربران 100 بوده است.

تستر می‌تواند Query زیر را اجرا کند:

SELECT COUNT(*)
FROM users;

سپس عملیات ثبت‌نام را انجام دهد و Query را دوباره اجرا کند.

SELECT COUNT(*)
FROM users;

اگر نتیجه به 101 رسیده باشد، می‌توان تأیید کرد که یک رکورد جدید ایجاد شده است.

البته این فقط یکی از بررسی‌ها است. ممکن است تعداد رکوردها افزایش پیدا کند اما رکورد اشتباه ایجاد شده باشد. بنابراین بهتر است در کنار COUNT، اطلاعات خود رکورد نیز بررسی شود.

استفاده از COUNT برای پیدا کردن داده‌های تکراری

یکی دیگر از کاربردهای مهم COUNT، پیدا کردن داده‌های تکراری است.

فرض کنید می‌خواهیم بررسی کنیم آیا یک ایمیل چند بار در جدول users ثبت شده است:

SELECT email, COUNT(*)
FROM users
GROUP BY email
HAVING COUNT(*) > 1;

این Query ایمیل‌هایی را پیدا می‌کند که بیش از یک بار در جدول وجود دارند.

emailCOUNT(*)
ali@example.com2
sara@example.com3

اگر Requirement سیستم می‌گوید هر ایمیل باید یکتا باشد، چنین نتیجه‌ای می‌تواند نشان‌دهنده یک مشکل باشد.

در اینجا با یک Query نسبتاً ساده، تستر می‌تواند یک مشکل Data Integrity را شناسایی کند.

COUNT و تست عملیات Delete

COUNT فقط برای بررسی ایجاد داده کاربرد ندارد.

فرض کنید قبل از حذف یک کاربر، تعداد رکوردهای جدول users برابر با 101 است.

بعد از انجام عملیات حذف، می‌توان Query زیر را اجرا کرد:

SELECT COUNT(*)
FROM users;

اگر نتیجه 100 باشد، یکی از انتظارات ما برآورده شده است.

اما باز هم باید توجه کنیم که کاهش تعداد رکوردها به‌تنهایی کافی نیست. باید مطمئن شویم همان رکورد موردنظر حذف شده است و عملیات حذف روی داده‌های دیگر تأثیر غیرمنتظره‌ای نگذاشته است.

یک نکته مهم درباره COUNT

تفاوت‌هایی بین حالت‌های مختلف COUNT وجود دارد. برای مثال:

COUNT(*)

و:

COUNT(email)

کاملاً یکسان نیستند.

COUNT(*) تعداد رکوردها را می‌شمارد، در حالی که COUNT(email) فقط مقادیری را در نظر می‌گیرد که مقدار email آن‌ها NULL نباشد.

این تفاوت زمانی اهمیت پیدا می‌کند که تستر بخواهد کامل بودن داده‌ها و وجود مقدار NULL را بررسی کند.

۱۱. NULL در دیتابیس و نحوه بررسی آن با SQL

یکی از مفاهیمی که تستر هنگام کار با دیتابیس حتماً باید با آن آشنا باشد، NULL است.

NULL به معنی نبودن مقدار یا مشخص نبودن مقدار است. این مفهوم با مقدار صفر (0)، رشته خالی ('') یا مقدار false تفاوت دارد.

برای مثال، فرض کنید جدول users شامل این اطلاعات باشد:

idnamephone
1Ali09120000000
2SaraNULL
3Reza09121111111

در رکورد مربوط به Sara، مقدار phone برابر NULL است؛ یعنی برای این کاربر شماره تلفنی ثبت نشده است.

اشتباه رایج در بررسی NULL

ممکن است تصور کنیم برای پیدا کردن رکوردهایی که مقدار phone آن‌ها خالی است، می‌توانیم بنویسیم:

SELECT *
FROM users
WHERE phone = NULL;

اما این روش صحیح نیست.

برای بررسی NULL باید از IS NULL استفاده کنیم:

SELECT *
FROM users
WHERE phone IS NULL;

به همین شکل، برای پیدا کردن رکوردهایی که مقدار phone آن‌ها NULL نیست:

SELECT *
FROM users
WHERE phone IS NOT NULL;

چرا NULL برای تستر مهم است؟

فرض کنید Requirement سیستم می‌گوید:

شماره تلفن هنگام ثبت‌نام الزامی است.

تستر می‌تواند بررسی کند که آیا رکوردهای بدون شماره تلفن در دیتابیس ایجاد شده‌اند یا خیر:

SELECT id, name, phone
FROM users
WHERE phone IS NULL;

اگر نتیجه شامل رکوردهایی باشد که نباید بدون شماره تلفن ایجاد می‌شدند، می‌تواند نشانه وجود یک مشکل باشد.

تفاوت NULL با مقدار خالی

این دو مورد را نباید با هم اشتباه گرفت.

NULL یعنی هیچ مقداری وجود ندارد.

اما مقدار خالی:

phone = ''

یعنی یک مقدار متنی وجود دارد که طول آن صفر است.

بنابراین این دو Query می‌توانند نتایج متفاوتی داشته باشند:

SELECT *
FROM users
WHERE phone IS NULL;
SELECT *
FROM users
WHERE phone = '';

در تست دیتابیس، بسته به Requirement باید مشخص باشد که سیستم در هر شرایطی باید NULL، مقدار خالی یا یک مقدار واقعی ذخیره کند.

ارتباط NULL با COUNT

همان‌طور که در بخش قبل دیدیم، COUNT نیز با NULL رفتار متفاوتی دارد.

فرض کنید جدول users شامل 100 رکورد باشد، اما فقط 80 کاربر شماره تلفن داشته باشند.

SELECT COUNT(*)
FROM users;

نتیجه 100 خواهد بود.

اما:

SELECT COUNT(phone)
FROM users;

نتیجه 80 خواهد بود؛ زیرا COUNT(phone) مقدارهای NULL را در شمارش خود لحاظ نمی‌کند.

این ویژگی می‌تواند برای تستر مفید باشد. مثلاً می‌توان از آن برای بررسی اینکه چه تعداد از کاربران اطلاعات یک فیلد مشخص را دارند استفاده کرد.

یک سناریوی واقعی

فرض کنید Requirement می‌گوید:

تمام سفارش‌های ثبت‌شده باید دارای تاریخ ثبت باشند.

تستر می‌تواند رکوردهای مشکل‌دار را پیدا کند:

SELECT id, user_id, created_at
FROM orders
WHERE created_at IS NULL;

اگر Query رکوردی برگرداند، باید بررسی شود که آیا وجود چنین رکوردی مطابق Requirement است یا خیر.

بنابراین، NULL فقط یک مفهوم SQL نیست؛ بلکه در اعتبارسنجی قوانین کسب‌وکار و کامل بودن داده‌ها نیز اهمیت زیادی دارد.

در بخش بعدی سراغ یکی از مهم‌ترین مباحث SQL برای تستر می‌رویم: JOIN و نحوه بررسی ارتباط بین داده‌های موجود در جدول‌های مختلف.

JOIN در SQL چیست و چرا برای تستر مهم است؟

در بسیاری از تست‌های دیتابیس، اطلاعات موردنیاز ما در یک جدول قرار ندارد. برای مثال، در یک فروشگاه اینترنتی، اطلاعات کاربران در جدول users و اطلاعات سفارش‌ها در جدول orders ذخیره می‌شود.

در چنین شرایطی، تستر باید بتواند اطلاعات این جدول‌ها را به یکدیگر مرتبط کند. این کار با استفاده از JOIN در SQL انجام می‌شود.

به زبان ساده، JOIN به ما اجازه می‌دهد اطلاعات مرتبط از چند جدول را در کنار هم ببینیم.

یک مثال ساده

فرض کنیم جدول users به شکل زیر باشد:

idnameemail
1Aliali@example.com
2Sarasara@example.com
3Rezareza@example.com

و جدول orders:

iduser_idamountstatus
1011500000paid
1021750000shipped
1032300000pending

در اینجا orders.user_id مشخص می‌کند هر سفارش متعلق به کدام کاربر است.

users.id = 1
        ↓
orders.user_id = 1

بنابراین دو سفارش با شماره‌های 101 و 102 متعلق به Ali هستند.

اگر بخواهیم نام کاربر و اطلاعات سفارش او را همزمان ببینیم، می‌توانیم از JOIN استفاده کنیم:

SELECT
    users.id,
    users.name,
    orders.id AS order_id,
    orders.amount,
    orders.status
FROM users
INNER JOIN orders
    ON users.id = orders.user_id;

نتیجه می‌تواند چیزی شبیه این باشد:

idnameorder_idamountstatus
1Ali101500000paid
1Ali102750000shipped
2Sara103300000pending

در اینجا اطلاعات دو جدول بر اساس رابطه زیر به هم متصل شده‌اند:

users.id = orders.user_id

INNER JOIN چیست؟

یکی از پرکاربردترین انواع JOIN، یعنی INNER JOIN، فقط رکوردهایی را برمی‌گرداند که بین دو جدول مطابقت داشته باشند.

SELECT
    users.name,
    orders.id AS order_id,
    orders.status
FROM users
INNER JOIN orders
    ON users.id = orders.user_id;

اگر کاربری در جدول users وجود داشته باشد ولی هیچ سفارشی نداشته باشد، در نتیجه این Query نمایش داده نمی‌شود.

این موضوع برای تستر مهم است، چون باید بداند چه داده‌هایی عمداً از نتیجه Query حذف می‌شوند.

LEFT JOIN چیست؟

نوع مهم دیگر LEFT JOIN است.

در LEFT JOIN تمام رکوردهای جدول سمت چپ نمایش داده می‌شوند، حتی اگر در جدول سمت راست رکورد مرتبطی وجود نداشته باشد.

SELECT
    users.id,
    users.name,
    orders.id AS order_id
FROM users
LEFT JOIN orders
    ON users.id = orders.user_id;

اگر Reza هیچ سفارشی نداشته باشد، نتیجه می‌تواند به این شکل باشد:

idnameorder_id
1Ali101
1Ali102
2Sara103
3RezaNULL

در اینجا NULL نشان می‌دهد برای Reza سفارش مرتبطی پیدا نشده است.

پیدا کردن کاربران بدون سفارش

یکی از کاربردهای بسیار مفید LEFT JOIN برای تستر، پیدا کردن رکوردهایی است که رکورد مرتبط ندارند.

SELECT
    users.id,
    users.name
FROM users
LEFT JOIN orders
    ON users.id = orders.user_id
WHERE orders.id IS NULL;

این Query کاربرانی را پیدا می‌کند که هیچ سفارشی ندارند.

البته اینکه این وضعیت Bug باشد یا نه، به Requirement بستگی دارد. ممکن است نداشتن سفارش برای یک کاربر کاملاً طبیعی باشد.

JOIN چه کاربردی در تست نرم‌افزار دارد؟

فرض کنیم در یک تست، کاربر از طریق UI یک سفارش ثبت کرده است.

ممکن است UI پیام زیر را نشان دهد:

Order created successfully

اما تستر فقط به این پیام اکتفا نمی‌کند.

می‌تواند با استفاده از JOIN بررسی کند که:

  • سفارش واقعاً در دیتابیس ایجاد شده است.
  • سفارش به کاربر درست متصل شده است.
  • user_id اشتباه ثبت نشده است.
  • مبلغ سفارش متعلق به همان سفارش است.
  • وضعیت سفارش درست ذخیره شده است.
SELECT
    users.name,
    users.email,
    orders.id AS order_id,
    orders.amount,
    orders.status
FROM users
INNER JOIN orders
    ON users.id = orders.user_id
WHERE users.email = 'ali@example.com';

این Query به تستر کمک می‌کند اطلاعات کاربر و سفارش او را همزمان بررسی کند.

یک نکته مهم برای تستر

در رابطه One-to-Many ممکن است یک رکورد از جدول اول، چندین رکورد در جدول دوم داشته باشد.

Ali
 ├── Order 101
 ├── Order 102
 └── Order 105

بنابراین اگر Query بالا سه ردیف برای Ali برگرداند، لزوماً به معنی وجود سه کاربر Ali نیست؛ بلکه ممکن است یک کاربر دارای سه سفارش باشد.

این نکته هنگام تحلیل نتایج Query بسیار مهم است و می‌تواند از برداشت اشتباه تستر جلوگیری کند.

در ادامه، مفاهیمی مثل GROUP BY و HAVING کمک می‌کنند بتوانیم همین داده‌ها را گروه‌بندی کنیم و مثلاً تعداد سفارش‌های هر کاربر را بررسی کنیم.

GROUP BY و HAVING در SQL برای تستر

گاهی اوقات فقط پیدا کردن رکوردها کافی نیست و تستر نیاز دارد داده‌ها را گروه‌بندی و شمارش کند.

برای مثال، ممکن است بخواهیم بدانیم:

  • هر کاربر چند سفارش دارد؟
  • چند سفارش با وضعیت paid داریم؟
  • چند کاربر فعال وجود دارد؟
  • کدام کاربران بیشتر از یک سفارش ثبت کرده‌اند؟
  • آیا داده‌های تکراری در دیتابیس وجود دارد؟

برای این نوع بررسی‌ها، دو عبارت مهم SQL یعنی GROUP BY و HAVING بسیار کاربردی هستند.

GROUP BY چیست؟

GROUP BY رکوردهایی را که مقدار مشترکی دارند در یک گروه قرار می‌دهد.

فرض کنیم جدول orders به شکل زیر باشد:

iduser_idamountstatus
1011500000paid
1021750000shipped
1032300000pending
1042450000paid
1051200000paid

اگر بخواهیم تعداد سفارش‌های هر کاربر را محاسبه کنیم، می‌توانیم بنویسیم:

SELECT
    user_id,
    COUNT(*) AS order_count
FROM orders
GROUP BY user_id;

نتیجه:

user_idorder_count
13
22

یعنی کاربر شماره 1 سه سفارش و کاربر شماره 2 دو سفارش دارد.

GROUP BY در تست نرم‌افزار چه کاربردی دارد؟

فرض کنید Requirement می‌گوید:

هر کاربر می‌تواند چند سفارش داشته باشد.

تستر می‌تواند با GROUP BY بررسی کند که تعداد سفارش‌های ثبت‌شده برای کاربران با چیزی که انتظار می‌رود مطابقت دارد.

SELECT
    user_id,
    COUNT(*) AS order_count
FROM orders
GROUP BY user_id
ORDER BY order_count DESC;

این Query کاربران را بر اساس تعداد سفارش‌هایشان نشان می‌دهد.

GROUP BY همراه با JOIN

می‌توانیم GROUP BY را با JOIN ترکیب کنیم تا به جای user_id، نام کاربر را ببینیم:

SELECT
    users.name,
    COUNT(orders.id) AS order_count
FROM users
LEFT JOIN orders
    ON users.id = orders.user_id
GROUP BY users.id, users.name;

نتیجه می‌تواند چیزی شبیه این باشد:

nameorder_count
Ali3
Sara2
Reza0

استفاده از LEFT JOIN باعث می‌شود حتی کاربری که هیچ سفارشی ندارد نیز در نتیجه نمایش داده شود.

این نوع Query برای بررسی ارتباط بین داده‌ها بسیار مفید است.

HAVING چیست؟

HAVING برای فیلتر کردن گروه‌ها بعد از GROUP BY استفاده می‌شود.

مثلاً فرض کنیم می‌خواهیم فقط کاربرانی را پیدا کنیم که بیشتر از یک سفارش دارند:

SELECT
    user_id,
    COUNT(*) AS order_count
FROM orders
GROUP BY user_id
HAVING COUNT(*) > 1;

نتیجه:

user_idorder_count
13
22

کاربرانی که فقط یک سفارش دارند در نتیجه نمایش داده نمی‌شوند.

تفاوت WHERE و HAVING

یک نکته مهم برای تستر این است که WHERE و HAVING کاربرد یکسانی ندارند.

  • WHERE → قبل از گروه‌بندی، رکوردها را فیلتر می‌کند.
  • HAVING → بعد از GROUP BY، گروه‌ها را فیلتر می‌کند.

مثلاً:

SELECT
    user_id,
    COUNT(*) AS order_count
FROM orders
WHERE status = 'paid'
GROUP BY user_id
HAVING COUNT(*) > 1;

در این Query ابتدا فقط سفارش‌های paid انتخاب می‌شوند، سپس بر اساس user_id گروه‌بندی شده و در نهایت فقط کاربرانی نمایش داده می‌شوند که بیشتر از یک سفارش پرداخت‌شده دارند.

یک کاربرد مهم: پیدا کردن داده‌های تکراری

GROUP BY و HAVING یکی از روش‌های مفید برای پیدا کردن Duplicate Data هستند.

فرض کنیم Requirement می‌گوید ایمیل کاربران باید Unique باشد.

می‌توانیم بررسی کنیم آیا ایمیلی بیش از یک بار در جدول وجود دارد:

SELECT
    email,
    COUNT(*) AS duplicate_count
FROM users
GROUP BY email
HAVING COUNT(*) > 1;

اگر Query هیچ نتیجه‌ای برنگرداند، یعنی در داده‌های فعلی ایمیل تکراری پیدا نشده است.

اما اگر مثلاً نتیجه زیر را ببینیم:

emailduplicate_count
ali@example.com2

تستر باید این مورد را بررسی کند؛ چون ممکن است نقض یک Business Rule یا Constraint باشد.

بنابراین GROUP BY و HAVING فقط دستورات آماری نیستند؛ برای Data Validation و پیدا کردن مشکلات داده‌ای نیز کاربرد زیادی دارند.

INSERT، UPDATE و DELETE در SQL

تا اینجا بیشتر Queryهایی را بررسی کردیم که برای خواندن و بررسی داده‌ها استفاده می‌شوند. اما در بعضی سناریوهای تست، لازم است تستر داده‌ای ایجاد کند، داده‌ای را تغییر دهد یا داده‌ای را حذف کند.

سه دستور مهم برای این کار عبارت‌اند از:

  • INSERT → ایجاد رکورد جدید
  • UPDATE → تغییر رکورد موجود
  • DELETE → حذف رکورد

این دستورات در محیط‌های تست می‌توانند بسیار کاربردی باشند، اما باید با احتیاط استفاده شوند؛ مخصوصاً در محیط‌هایی که داده‌های واقعی وجود دارند.

INSERT؛ ایجاد داده جدید

با INSERT می‌توان یک رکورد جدید به جدول اضافه کرد.

INSERT INTO users (name, email, status)
VALUES ('Ali', 'ali@example.com', 'active');

بعد از اجرای این دستور، یک کاربر جدید در جدول users ایجاد می‌شود.

تستر می‌تواند سپس با SELECT بررسی کند که رکورد به‌درستی ایجاد شده است:

SELECT id, name, email, status
FROM users
WHERE email = 'ali@example.com';

این روش می‌تواند برای آماده‌سازی Test Data نیز مفید باشد.

مثلاً قبل از اجرای یک Test Case که به یک کاربر فعال نیاز دارد، تستر می‌تواند در محیط تست یک کاربر مناسب ایجاد کند.

UPDATE؛ تغییر داده

UPDATE برای تغییر اطلاعات یک یا چند رکورد استفاده می‌شود.

مثلاً فرض کنیم وضعیت کاربر باید از inactive به active تغییر کند:

UPDATE users
SET status = 'active'
WHERE id = 25;

بعد می‌توان نتیجه را بررسی کرد:

SELECT id, name, status
FROM users
WHERE id = 25;

این موضوع برای تست تغییر اطلاعات بسیار کاربردی است.

برای مثال، اگر کاربر از طریق UI وضعیت یا اطلاعات خاصی را تغییر دهد، تستر می‌تواند بررسی کند که آیا تغییر موردنظر واقعاً در دیتابیس ذخیره شده است یا خیر.

DELETE؛ حذف داده

DELETE برای حذف رکورد استفاده می‌شود.

DELETE FROM users
WHERE id = 25;

سپس می‌توان بررسی کرد که رکورد واقعاً حذف شده است:

SELECT *
FROM users
WHERE id = 25;

اگر Query نتیجه‌ای برنگرداند، یعنی رکورد موردنظر در جدول پیدا نشده است.

مهم‌ترین نکته در UPDATE و DELETE

یکی از خطرناک‌ترین اشتباهات هنگام کار با SQL، فراموش کردن WHERE است.

مثلاً این دستور را ببینید:

UPDATE users
SET status = 'inactive';

در این حالت، وضعیت تمام کاربران تغییر می‌کند.

یا:

DELETE FROM users;

این دستور می‌تواند تمام رکوردهای جدول را حذف کند.

بنابراین در کار واقعی، مخصوصاً روی Production Database، اجرای دستورات UPDATE و DELETE بدون بررسی دقیق بسیار خطرناک است.

یک روش ساده برای کاهش خطا این است که ابتدا همان شرط را با SELECT بررسی کنیم.

SELECT *
FROM users
WHERE id = 25;

اگر مطمئن شدیم رکورد موردنظر همان چیزی است که می‌خواهیم، سپس:

UPDATE users
SET status = 'active'
WHERE id = 25;

استفاده از INSERT، UPDATE و DELETE در تست

این دستورات می‌توانند در سناریوهای مختلف تست مفید باشند.

INSERT

ایجاد داده اولیه برای اجرای Test Case:

INSERT INTO users (name, email, status)
VALUES ('Test User', 'test@example.com', 'active');

UPDATE

آماده‌سازی یک وضعیت خاص برای تست:

UPDATE users
SET status = 'inactive'
WHERE email = 'test@example.com';

DELETE

پاک‌سازی داده‌های ایجادشده در محیط تست:

DELETE FROM users
WHERE email = 'test@example.com';

البته نحوه ایجاد و پاک‌سازی Test Data به ساختار پروژه و سیاست‌های تیم بستگی دارد و در بعضی پروژه‌ها این کار از طریق Script، API یا ابزارهای مخصوص تست انجام می‌شود.

یک نکته مهم برای تستر

تستر الزاماً قرار نیست همیشه مستقیماً با INSERT، UPDATE و DELETE داده‌ها را مدیریت کند.

در بسیاری از پروژه‌ها، هدف اصلی تستر این است که بتواند:

  1. داده مناسب را در محیط تست داشته باشد.
  2. عملیات انجام‌شده توسط نرم‌افزار را در دیتابیس بررسی کند.
  3. در صورت نیاز، داده‌های خاصی برای تست ایجاد یا اصلاح کند.
  4. نتیجه عملیات را با Requirement مقایسه کند.

بنابراین یادگیری این دستورات باید با تمرکز بر کاربرد آن‌ها در تست نرم‌افزار باشد، نه تبدیل شدن به یک متخصص Database Administration.

تست Primary Key و Foreign Key

یکی از مهم‌ترین بخش‌های تست دیتابیس، بررسی روابط بین جداول است. در این بخش، دو مفهوم Primary Key و Foreign Key اهمیت زیادی دارند.

همان‌طور که در بخش مفاهیم پایه گفتیم، Primary Key یک رکورد را به‌صورت منحصربه‌فرد مشخص می‌کند و Foreign Key برای ایجاد ارتباط بین جداول استفاده می‌شود.

Primary Key چیست؟

فرض کنیم جدول users به شکل زیر باشد:

idnameemail
1Aliali@example.com
2Sarasara@example.com
3Rezareza@example.com

در این جدول، ستون id می‌تواند Primary Key باشد.

بنابراین انتظار داریم:

  • مقدار id تکراری نباشد.
  • مقدار id برای هر رکورد منحصربه‌فرد باشد.
  • در حالت معمول id مقدار NULL نداشته باشد.

تستر می‌تواند برای پیدا کردن IDهای تکراری از Query زیر استفاده کند:

SELECT
    id,
    COUNT(*) AS count_id
FROM users
GROUP BY id
HAVING COUNT(*) > 1;

اگر Query نتیجه‌ای نداشته باشد، در داده‌های بررسی‌شده ID تکراری پیدا نشده است.

Foreign Key چیست؟

حالا فرض کنیم جدول orders به شکل زیر باشد:

iduser_idamount
1011500000
1021750000
1032300000

در اینجا user_id به users.id مربوط است.

users
id
│
├── 1 ──────────┐
│               │
└── 2 ──────┐   │
            ↓   ↓
          orders
          user_id

در نتیجه، orders.user_id می‌تواند Foreign Key باشد که به users.id اشاره می‌کند.

این رابطه به دیتابیس کمک می‌کند تا ارتباط بین سفارش و صاحب سفارش مشخص باشد.

چرا تست Foreign Key مهم است؟

فرض کنید در جدول orders رکورد زیر وجود داشته باشد:

iduser_idamount
104999400000

اما کاربری با id = 999 در جدول users وجود ندارد.

در این حالت یک Orphan Record یا رکورد بدون مرجع معتبر داریم.

تستر می‌تواند با LEFT JOIN چنین مواردی را پیدا کند:

SELECT
    orders.id,
    orders.user_id,
    orders.amount
FROM orders
LEFT JOIN users
    ON orders.user_id = users.id
WHERE users.id IS NULL;

اگر نتیجه‌ای برگردد، یعنی سفارش‌هایی وجود دارند که کاربر مرتبط با آن‌ها در جدول users پیدا نشده است.

البته اینکه چنین وضعیتی Bug محسوب شود یا نه، به طراحی دیتابیس و قوانین پروژه بستگی دارد.

بررسی NULL بودن Foreign Key

در بعضی سیستم‌ها ممکن است یک رکورد الزاماً به رکورد دیگری وابسته نباشد.

مثلاً فرض کنیم هر سفارش باید حتماً متعلق به یک کاربر باشد. در این صورت user_id نباید NULL باشد.

تستر می‌تواند این موارد را بررسی کند:

SELECT
    id,
    user_id
FROM orders
WHERE user_id IS NULL;

اگر نتیجه‌ای وجود داشته باشد، باید بررسی شود که آیا با Requirement و Constraint دیتابیس سازگار است یا خیر.

تست ارتباط One-to-Many

یکی از رایج‌ترین روابط در نرم‌افزارها، رابطه One-to-Many است.

برای مثال:

یک کاربر می‌تواند چند سفارش داشته باشد.

User
  │
  ├── Order 101
  ├── Order 102
  └── Order 103

تستر می‌تواند با Query زیر تعداد سفارش‌های هر کاربر را بررسی کند:

SELECT
    user_id,
    COUNT(*) AS order_count
FROM orders
GROUP BY user_id;

و اگر بخواهد نام کاربران را نیز ببیند:

SELECT
    users.id,
    users.name,
    COUNT(orders.id) AS order_count
FROM users
LEFT JOIN orders
    ON users.id = orders.user_id
GROUP BY users.id, users.name;

این نوع بررسی در تست Data Integrity بسیار مفید است.

تستر هنگام بررسی Primary Key و Foreign Key به چه چیزهایی توجه کند؟

  • آیا Primary Key برای هر رکورد منحصربه‌فرد است؟
  • آیا Primary Key مقدار NULL دارد؟
  • آیا Foreign Key به رکورد معتبر در جدول مقصد اشاره می‌کند؟
  • آیا رکوردهای بدون مرجع وجود دارند؟
  • آیا روابط تعریف‌شده در Requirement با ساختار دیتابیس مطابقت دارند؟
  • آیا حذف یا تغییر یک رکورد، روی رکوردهای مرتبط تأثیر مورد انتظار را دارد؟

این بررسی‌ها کمک می‌کنند مطمئن شویم فقط خود داده‌ها درست نیستند، بلکه ارتباط بین داده‌ها نیز صحیح است.

ارتباط تست دیتابیس با API Testing

در بسیاری از پروژه‌های مدرن، API نقش واسطه بین Frontend و Backend را دارد. بنابراین تستر می‌تواند علاوه بر بررسی Response مربوط به API، دیتابیس را نیز بررسی کند تا مطمئن شود اطلاعات به شکل صحیح ذخیره یا تغییر کرده‌اند.

به بیان ساده:

UI
 ↓
API
 ↓
Application
 ↓
Database

در این حالت، تستر می‌تواند یک درخواست را از طریق API ارسال کند و سپس نتیجه آن را در دیتابیس بررسی کند.

یک مثال ساده

فرض کنید API زیر برای ایجاد کاربر استفاده می‌شود:

POST /api/users

و Body درخواست:

{
  "name": "Ali",
  "email": "ali@example.com"
}

API ممکن است Response زیر را برگرداند:

{
  "id": 125,
  "name": "Ali",
  "email": "ali@example.com",
  "status": "active"
}

در نگاه اول ممکن است تست موفق به نظر برسد؛ اما تستر می‌تواند بررسی کند که آیا این اطلاعات واقعاً در دیتابیس ذخیره شده‌اند یا خیر.

SELECT
    id,
    name,
    email,
    status
FROM users
WHERE id = 125;

حالا نتیجه دیتابیس را با Response API مقایسه می‌کنیم.

FieldAPI ResponseDatabase
id125125
nameAliAli
emailali@example.comali@example.com
statusactiveactive

اگر این مقادیر مطابق باشند، یک بخش مهم از جریان ایجاد کاربر تأیید شده است.

تست Update از طریق API و بررسی دیتابیس

فرض کنیم کاربر از طریق API ایمیل خود را تغییر می‌دهد:

PUT /api/users/125

با Body:

{
  "email": "newemail@example.com"
}

API ممکن است پاسخ موفقیت‌آمیز برگرداند:

{
  "id": 125,
  "email": "newemail@example.com"
}

اما تستر می‌تواند با SQL بررسی کند که مقدار واقعاً در دیتابیس تغییر کرده است:

SELECT
    id,
    email
FROM users
WHERE id = 125;

اگر دیتابیس همچنان مقدار قبلی را داشته باشد، با وجود اینکه API Response ظاهراً موفق است، احتمال وجود یک مشکل در Backend یا فرآیند ذخیره‌سازی داده وجود دارد.

بررسی DELETE از طریق API

فرض کنیم API برای حذف کاربر استفاده می‌شود:

DELETE /api/users/125

بعد از دریافت Response موفق، تستر می‌تواند بررسی کند که آیا رکورد موردنظر واقعاً حذف شده است:

SELECT *
FROM users
WHERE id = 125;

اگر رکورد همچنان وجود داشته باشد، باید بررسی شود که آیا:

  • حذف به‌صورت Soft Delete انجام شده است؟
  • API فقط وضعیت رکورد را تغییر داده است؟
  • عملیات حذف با خطا مواجه شده است؟
  • رفتار سیستم مطابق Requirement است؟

بنابراین همیشه نباید صرفاً با مشاهده 200 یا 204 نتیجه بگیریم که داده از دیتابیس حذف شده است.

بررسی Data Integrity بین API و Database

یکی از کاربردهای مهم این روش، بررسی Data Integrity است.

فرض کنید API برای ایجاد سفارش استفاده می‌شود:

POST /api/orders

و درخواست شامل موارد زیر است:

{
  "userId": 25,
  "amount": 750000,
  "status": "paid"
}

بعد از اجرای API، تستر می‌تواند بررسی کند:

  1. آیا سفارش ایجاد شده است؟
  2. آیا user_id درست ذخیره شده است؟
  3. آیا مبلغ صحیح است؟
  4. آیا وضعیت سفارش درست ذخیره شده است؟
  5. آیا سفارش به کاربر درست مرتبط شده است؟
SELECT
    orders.id,
    orders.user_id,
    users.name,
    orders.amount,
    orders.status
FROM orders
INNER JOIN users
    ON users.id = orders.user_id
WHERE orders.user_id = 25
ORDER BY orders.id DESC;

در اینجا تستر نه‌تنها خود سفارش، بلکه ارتباط آن با کاربر را نیز بررسی می‌کند.

آیا همیشه باید دیتابیس را بعد از API تست کنیم؟

خیر.

تست دیتابیس در کنار API Testing یک تکنیک مفید است، اما قرار نیست برای هر Test Case حتماً مستقیماً دیتابیس را بررسی کنیم.

اگر هدف تست فقط بررسی رفتار قابل مشاهده API باشد، ممکن است بررسی Request و Response کافی باشد.

اما در سناریوهایی مانند موارد زیر، بررسی دیتابیس می‌تواند ارزش زیادی داشته باشد:

  • ایجاد داده جدید
  • تغییر داده
  • حذف داده
  • بررسی Data Integrity
  • بررسی روابط بین جداول
  • بررسی محاسبات Backend
  • بررسی Business Ruleهایی که در Response قابل مشاهده نیستند
  • بررسی مشکلاتی که فقط در Backend یا Database قابل مشاهده‌اند

در واقع، تستر می‌تواند API را از بیرون بررسی کند و دیتابیس را برای اعتبارسنجی نتیجه داخلی عملیات مورد استفاده قرار دهد.

این ارتباط بین API و دیتابیس یکی از دلایلی است که دانستن SQL برای تسترهای Backend و Automation بسیار ارزشمند است.

ارتباط تست دیتابیس با UI Testing

کاربر معمولاً مستقیماً با دیتابیس کار نمی‌کند. او از طریق UI عملیاتی را انجام می‌دهد و نتیجه را در همان رابط کاربری مشاهده می‌کند.

اما پشت این عملیات معمولاً چند مرحله اتفاق می‌افتد:

User
 ↓
UI
 ↓
API / Backend
 ↓
Database

تستر می‌تواند در بعضی سناریوها علاوه بر بررسی نتیجه در UI، دیتابیس را نیز بررسی کند تا مطمئن شود عملیات در لایه‌های مختلف سیستم به‌درستی انجام شده است.

یک مثال ساده؛ ثبت‌نام کاربر

فرض کنید کاربر در صفحه ثبت‌نام اطلاعات زیر را وارد می‌کند:

Name: Ali
Email: ali@example.com
Password: ********

و روی دکمه Register کلیک می‌کند.

UI ممکن است پیام زیر را نمایش دهد:

Registration successful

در اینجا یک تست UI می‌تواند بررسی کند که پیام موفقیت نمایش داده شده است.

اما تستر می‌تواند یک مرحله دیگر نیز اضافه کند و دیتابیس را بررسی کند:

SELECT
    id,
    name,
    email,
    status
FROM users
WHERE email = 'ali@example.com';

حالا می‌توان بررسی کرد که:

  • کاربر واقعاً ایجاد شده است.
  • نام درست ذخیره شده است.
  • ایمیل درست ذخیره شده است.
  • وضعیت کاربر مطابق Requirement است.
  • رکورد تکراری ایجاد نشده است.

چرا بررسی UI به‌تنهایی همیشه کافی نیست؟

فرض کنید بعد از تغییر آدرس کاربر، UI پیام زیر را نشان دهد:

Address updated successfully

ممکن است همه‌چیز در ظاهر درست باشد، اما در Backend مقدار اشتباه ذخیره شده باشد.

مثلاً کاربر آدرس جدیدی وارد کرده است:

Tehran, Valiasr St.

اما در دیتابیس مقدار قدیمی باقی مانده است.

تستر می‌تواند با Query زیر بررسی کند:

SELECT
    id,
    user_id,
    address
FROM user_addresses
WHERE user_id = 25;

در این حالت، تستر می‌تواند نتیجه UI را با داده واقعی دیتابیس مقایسه کند.

یک مثال مهم‌تر؛ ثبت سفارش

فرض کنیم کاربر از طریق UI یک سفارش با مبلغ 750000 تومان ثبت می‌کند.

در UI ممکن است اطلاعات زیر نمایش داده شود:

Order ID: 1025
Amount: 750000
Status: Paid

تستر می‌تواند بررسی کند که همین اطلاعات در دیتابیس نیز به شکل صحیح ذخیره شده‌اند:

SELECT
    id,
    user_id,
    amount,
    status
FROM orders
WHERE id = 1025;

اگر نتیجه مثلاً این باشد:

iduser_idamountstatus
102525750000paid

می‌توانیم داده ذخیره‌شده را با اطلاعات مورد انتظار مقایسه کنیم.

بررسی ارتباط چند جدول بعد از یک تست UI

گاهی بررسی یک جدول کافی نیست.

مثلاً بعد از ثبت سفارش، انتظار داریم:

User
  ↓
Order
  ↓
Order Items
  ↓
Product

یعنی یک سفارش باید به کاربر، محصولات و آیتم‌های سفارش مربوط باشد.

تستر می‌تواند با JOIN این روابط را بررسی کند:

SELECT
    users.name,
    orders.id AS order_id,
    orders.amount,
    order_items.product_id,
    order_items.quantity
FROM users
INNER JOIN orders
    ON users.id = orders.user_id
INNER JOIN order_items
    ON orders.id = order_items.order_id
WHERE orders.id = 1025;

این Query می‌تواند کمک کند بررسی کنیم آیا اطلاعات مرتبط با سفارش به شکل صحیح در جداول مختلف ذخیره شده‌اند یا خیر.

تست UI و دیتابیس؛ چه چیزی را باید بررسی کنیم؟

در چنین سناریوهایی بهتر است تستر از ابتدا مشخص کند چه چیزی قرار است اعتبارسنجی شود.

عملیات در UIبررسی در Database
ثبت کاربرایجاد رکورد جدید
ویرایش پروفایلتغییر صحیح اطلاعات
ثبت سفارشایجاد Order
تغییر وضعیت سفارشتغییر status
حذف اطلاعاتحذف یا Soft Delete
افزودن محصول به سبدایجاد یا تغییر رکورد مرتبط
ثبت پرداختذخیره صحیح اطلاعات پرداخت

نکته مهم این است که بررسی دیتابیس نباید صرفاً برای زیاد کردن تعداد مراحل تست انجام شود. باید زمانی استفاده شود که اعتبارسنجی داده ذخیره‌شده ارزش تستی داشته باشد.

UI → API → Database

در نهایت، یک تستر می‌تواند یک عملیات را در چند لایه دنبال کند:

UI
 │
 │  ثبت سفارش
 ↓
API
 │
 │  POST /orders
 ↓
Backend
 │
 │  Business Logic
 ↓
Database
 │
 │  INSERT
 ↓
Stored Data

بنابراین اگر UI نتیجه اشتباهی نشان دهد، تستر با داشتن دید مناسب نسبت به API و دیتابیس می‌تواند راحت‌تر تشخیص دهد مشکل احتمالاً در کدام بخش قرار دارد.

این موضوع مخصوصاً در Integration Testing و تست‌های End-to-End اهمیت پیدا می‌کند.

Test Data در تست دیتابیس

یکی از موضوعات مهم در تست دیتابیس، Test Data یا داده‌های تست است. حتی اگر Test Case به‌درستی طراحی شده باشد، داده نامناسب می‌تواند باعث شود نتیجه تست قابل اعتماد نباشد.

برای مثال، اگر بخواهیم قابلیت ورود کاربران را تست کنیم، فقط داشتن یک کاربر کافی نیست. ممکن است لازم باشد کاربران مختلفی با وضعیت‌های متفاوت داشته باشیم:

وضعیت کاربرمثال
فعالactive
غیرفعالinactive
مسدودشدهblocked
بدون تأیید ایمیلunverified

هرکدام از این داده‌ها می‌توانند برای یک سناریوی متفاوت استفاده شوند.

چرا Test Data اهمیت دارد؟

فرض کنید Requirement می‌گوید:

فقط کاربران فعال می‌توانند سفارش ثبت کنند.

برای تست این Requirement حداقل به دو کاربر نیاز داریم:

User A → active
User B → inactive

سپس می‌توانیم بررسی کنیم:

  • User A می‌تواند سفارش ثبت کند.
  • User B نمی‌تواند سفارش ثبت کند.
  • اطلاعات سفارش فقط برای کاربر مجاز ایجاد می‌شود.
  • وضعیت کاربر در دیتابیس درست بررسی می‌شود.

برای آماده‌سازی داده در محیط تست، ممکن است از INSERT استفاده کنیم:

INSERT INTO users (name, email, status)
VALUES ('Active Test User', 'active@test.com', 'active');
INSERT INTO users (name, email, status)
VALUES ('Inactive Test User', 'inactive@test.com', 'inactive');

Test Data باید چه ویژگی‌هایی داشته باشد؟

داده‌های تست باید تا حد امکان با هدف Test Case مرتبط باشند.

برای مثال، اگر می‌خواهیم اعتبارسنجی ایمیل را تست کنیم، می‌توانیم داده‌های مختلفی داشته باشیم:

valid@example.com
user.name@example.com
user+test@example.com
invalid-email
@test.com
user@

یا برای تست محدودیت مبلغ:

0
1
100000
999999
1000000
1000001

این نوع داده‌ها به تستر کمک می‌کنند Boundary Valueها و حالت‌های مختلف Business Rule را بررسی کند.

داده معتبر و نامعتبر

در تست نرم‌افزار معمولاً فقط داده‌های صحیح را بررسی نمی‌کنیم.

برای مثال، اگر ستون email باید مقدار معتبر داشته باشد، می‌توانیم دو گروه داده داشته باشیم:

Valid Data

ali@example.com
sara@example.com

Invalid Data

ali@
@example.com
ali

هدف این است که بررسی کنیم سیستم در هر دو حالت رفتار مورد انتظار را دارد.

Test Data و NULL

همان‌طور که در بخش NULL دیدیم، وجود یا عدم وجود مقدار نیز می‌تواند بخشی از تست باشد.

مثلاً اگر شماره تلفن اختیاری باشد:

INSERT INTO users (name, email, phone)
VALUES ('Test User', 'test@example.com', NULL);

سپس باید بررسی کنیم که سیستم با این داده به شکل صحیح رفتار می‌کند.

اما اگر phone یک فیلد اجباری باشد، همین داده می‌تواند یک سناریوی منفی باشد و باید بررسی کنیم که سیستم از ثبت آن جلوگیری می‌کند.

Test Data و Duplicate

یکی دیگر از موارد مهم، بررسی داده‌های تکراری است.

فرض کنیم ایمیل کاربران باید Unique باشد.

تستر می‌تواند ابتدا یک کاربر ایجاد کند:

INSERT INTO users (name, email)
VALUES ('Ali', 'ali@example.com');

سپس تلاش برای ایجاد کاربر دیگری با همان ایمیل را بررسی کند.

در نهایت می‌توان با Query زیر بررسی کرد که آیا Duplicate ایجاد شده است:

SELECT
    email,
    COUNT(*) AS count
FROM users
GROUP BY email
HAVING COUNT(*) > 1;

اگر نتیجه‌ای وجود داشته باشد، باید بررسی شود که آیا Constraint یا Business Rule مربوط به Unique بودن ایمیل به‌درستی عمل کرده است یا خیر.

پاک‌سازی Test Data

بعد از اجرای تست، گاهی لازم است داده‌های ایجادشده پاک شوند تا روی تست‌های بعدی تأثیر نگذارند.

DELETE FROM users
WHERE email = 'test@example.com';

اما این کار نیز باید با دقت انجام شود.

بهتر است داده‌های تست به شکلی ایجاد شوند که به‌راحتی قابل شناسایی باشند؛ مثلاً استفاده از یک الگوی مشخص:

test_user_001@example.com
test_user_002@example.com

این کار پاک‌سازی و مدیریت Test Data را ساده‌تر می‌کند.

یک نکته مهم

در پروژه‌های واقعی، همیشه لازم نیست تستر خودش مستقیماً با SQL داده ایجاد و حذف کند.

ممکن است Test Data از طریق موارد زیر آماده شود:

  • API
  • Test Script
  • Fixture
  • Test Framework
  • Database Script
  • ابزارهای مخصوص مدیریت داده‌های تست

مهم این است که تستر بداند برای اجرای یک سناریو چه داده‌ای لازم دارد و وضعیت داده‌ها چگونه می‌تواند روی نتیجه تست تأثیر بگذارد.

اشتباهات رایج در تست دیتابیس

تست دیتابیس فقط به معنی نوشتن چند Query و بررسی نتیجه نیست. نحوه اجرای Query، انتخاب داده مناسب و تفسیر نتیجه نیز اهمیت زیادی دارد.

برخی اشتباهات رایج می‌توانند باعث شوند تستر نتیجه نادرستی بگیرد یا حتی به داده‌های محیط تست آسیب بزند.

۱. بررسی فقط وجود رکورد

یکی از اشتباهات رایج این است که تستر فقط بررسی کند رکورد ایجاد شده یا نه.

SELECT *
FROM orders
WHERE id = 1025;

اگر رکورد وجود داشته باشد، ممکن است تستر نتیجه را موفق در نظر بگیرد.

اما وجود رکورد به‌تنهایی کافی نیست.

باید مواردی مانند این‌ها نیز بررسی شوند:

  • user_id درست است؟
  • مبلغ درست است؟
  • وضعیت درست است؟
  • تاریخ درست است؟
  • ارتباط با جداول دیگر صحیح است؟

بنابراین باید محتوای داده و روابط آن نیز اعتبارسنجی شوند.

۲. استفاده اشتباه از NULL

یکی دیگر از اشتباهات رایج، مقایسه NULL با = است.

روش اشتباه:

WHERE phone = NULL

روش صحیح:

WHERE phone IS NULL

و برای پیدا کردن رکوردهایی که مقدار دارند:

WHERE phone IS NOT NULL

این تفاوت ساده می‌تواند باعث شود Query نتیجه مورد انتظار را برنگرداند.

۳. فراموش کردن WHERE در UPDATE و DELETE

این مورد یکی از خطرناک‌ترین اشتباهات است.

UPDATE users
SET status = 'inactive';

این دستور می‌تواند وضعیت تمام کاربران را تغییر دهد.

یا:

DELETE FROM users;

می‌تواند تمام رکوردهای جدول را حذف کند.

بهتر است قبل از اجرای چنین دستورهایی ابتدا همان شرط را با SELECT بررسی کنیم:

SELECT *
FROM users
WHERE id = 25;

و بعد از اطمینان:

UPDATE users
SET status = 'inactive'
WHERE id = 25;

۴. فرض کردن اینکه Response موفق API یعنی دیتابیس هم درست است

فرض کنید API پاسخ 200 OK برگرداند.

این موضوع نشان می‌دهد درخواست از دید API با موفقیت پردازش شده، اما لزوماً به این معنی نیست که تمام داده‌ها دقیقاً مطابق انتظار در دیتابیس ذخیره شده‌اند.

در سناریوهای مناسب، تستر می‌تواند نتیجه را در دیتابیس نیز بررسی کند.

۵. نادیده گرفتن روابط بین جداول

ممکن است اطلاعات یک سفارش درست باشد، اما به کاربر اشتباه متصل شده باشد.

Order 1025
   ↓
user_id = 30

در حالی که سفارش واقعاً باید متعلق به کاربر 25 باشد.

بنابراین در تست دیتابیس فقط مقدار هر ستون را جداگانه بررسی نمی‌کنیم؛ Relationship بین داده‌ها نیز اهمیت دارد.

۶. استفاده از داده‌های تست نامناسب

اگر Test Data شرایط واقعی سناریو را پوشش ندهد، نتیجه تست نیز قابل اعتماد نخواهد بود.

مثلاً اگر Requirement می‌گوید:

کاربران مسدودشده نمی‌توانند سفارش ثبت کنند.

اما تستر فقط با یک کاربر active تست انجام دهد، بخش مهمی از رفتار سیستم بررسی نشده است.

بنابراین باید برای سناریوهای مختلف، داده مناسب داشته باشیم:

Active User
Inactive User
Blocked User
Unverified User

۷. برداشت اشتباه از نتیجه JOIN

در رابطه One-to-Many ممکن است یک کاربر چندین بار در نتیجه Query دیده شود.

Ali → Order 101
Ali → Order 102
Ali → Order 103

این به معنی وجود سه رکورد برای Ali در جدول users نیست.

بلکه به دلیل JOIN شدن یک کاربر با چند سفارش، نام او چند بار نمایش داده شده است.

شناخت ساختار دیتابیس برای تفسیر صحیح چنین نتایجی ضروری است.

۸. تست نکردن داده‌های منفی و Boundary

گاهی تستر فقط داده‌های معمولی را بررسی می‌کند.

مثلاً برای یک فیلد مبلغ:

100
500000
1000000

اما اگر Requirement محدودیت خاصی داشته باشد، باید مقادیر مرزی و نامعتبر نیز بررسی شوند:

0
1
999999
1000000
1000001

این موضوع می‌تواند به پیدا کردن خطاهای Business Logic کمک کند.

۹. اجرای Queryهای مخرب روی محیط اشتباه

تستر باید همیشه بداند به کدام Database متصل است.

اجرای یک Query روی محیط Production در حالی که تصور می‌کنیم روی Test Environment هستیم، می‌تواند پیامدهای جدی داشته باشد.

به‌خصوص هنگام استفاده از:

UPDATE
DELETE
INSERT

باید محیط، Database و شرط Query با دقت بررسی شوند.

جمع‌بندی

برای یک تستر، مهم‌ترین نکته این است که تست دیتابیس را صرفاً به اجرای SQL محدود نکند.

یک تست خوب باید بتواند به این سؤال پاسخ دهد:

آیا داده‌ای که نرم‌افزار تولید یا تغییر داده، از نظر مقدار، ساختار، ارتباط و قوانین کسب‌وکار واقعاً درست است؟

آیا تستر باید SQL حرفه‌ای بلد باشد؟

یکی از سؤال‌های رایج برای افرادی که وارد حوزه Software Testing می‌شوند این است که:

آیا برای تست نرم‌افزار باید SQL را در حد یک متخصص دیتابیس یاد بگیرم؟

پاسخ کوتاه این است: خیر.

تستر معمولاً نیازی ندارد در حد یک Database Administrator یا Database Developer با SQL کار کند؛ اما داشتن مهارت SQL در سطح کاربردی می‌تواند توانایی او را در تست و تحلیل مشکلات به شکل قابل توجهی افزایش دهد.

یک تستر چه مقدار SQL باید بداند؟

برای شروع، بهتر است تستر بتواند Queryهایی برای خواندن، فیلتر کردن، شمارش و ارتباط دادن داده‌ها بنویسد.

مهم‌ترین موارد عبارت‌اند از:

  • SELECT
  • WHERE
  • AND / OR
  • ORDER BY
  • LIKE
  • IN / NOT IN
  • BETWEEN
  • COUNT
  • DISTINCT
  • JOIN
  • GROUP BY
  • HAVING
  • IS NULL / IS NOT NULL

همچنین آشنایی با دستورات INSERT، UPDATE و DELETE برای کار با Test Data مفید است.

با همین مجموعه، تستر می‌تواند بخش بزرگی از نیازهای روزمره خود در تست دیتابیس را پوشش دهد.

آیا تستر باید SQL را حفظ کند؟

خیر.

هدف یادگیری SQL برای تستر، حفظ کردن تعداد زیادی دستور نیست.

مهم‌تر از حفظ Syntax این است که تستر بتواند مسئله را به یک Query مناسب تبدیل کند.

مثلاً اگر Requirement می‌گوید:

هر کاربر باید ایمیل منحصربه‌فرد داشته باشد.

تستر باید بتواند به این فکر کند:

چطور ایمیل‌های تکراری را پیدا کنم؟

و سپس Query مناسبی بنویسد:

SELECT
    email,
    COUNT(*) AS count
FROM users
GROUP BY email
HAVING COUNT(*) > 1;

بنابراین تفکر تستی مهم‌تر از حفظ کردن Syntax است.

SQL در Manual Testing

حتی در Manual Testing نیز SQL می‌تواند بسیار کاربردی باشد.

فرض کنید تستر در UI یک سفارش ثبت کرده است.

به جای اینکه فقط پیام زیر را ببیند:

Order created successfully

می‌تواند اطلاعات دیتابیس را نیز بررسی کند:

SELECT
    id,
    user_id,
    amount,
    status
FROM orders
WHERE id = 1025;

در نتیجه تستر می‌تواند بررسی کند که آیا داده واقعاً مطابق انتظار ذخیره شده است.

SQL در Automation Testing

SQL در Automation Testing نیز می‌تواند کاربرد داشته باشد.

مثلاً یک تست خودکار می‌تواند:

  1. داده موردنیاز را آماده کند.
  2. یک عملیات را از طریق UI یا API انجام دهد.
  3. دیتابیس را بررسی کند.
  4. نتیجه را با Expected Result مقایسه کند.
Test
 ↓
UI / API
 ↓
Application
 ↓
Database
 ↓
Validation

البته نحوه اتصال تست اتوماتیک به دیتابیس به زبان برنامه‌نویسی، Framework و معماری پروژه بستگی دارد.

برای کسی که قصد دارد در آینده وارد Automation Testing شود، داشتن SQL کاربردی یک مهارت ارزشمند محسوب می‌شود.

چه زمانی SQL بیشتری لازم می‌شود؟

سطح موردنیاز SQL به نوع کاری که تستر انجام می‌دهد بستگی دارد.

برای یک Manual Tester، معمولاً Queryهای ساده و متوسط می‌توانند بخش زیادی از نیازها را پوشش دهند.

برای یک Automation Tester، علاوه بر این موارد، توانایی استفاده از SQL در Scriptها و تست‌های خودکار اهمیت بیشتری پیدا می‌کند.

در پروژه‌های Backend، API، Data-intensive یا پیچیده نیز ممکن است نیاز به Queryهای پیشرفته‌تر وجود داشته باشد.

بنابراین بهتر است SQL را مرحله‌به‌مرحله یاد گرفت و متناسب با نیاز شغلی عمیق‌تر شد.

نکته مهم: لازم نیست قبل از شروع تست نرم‌افزار، SQL را به‌صورت کامل یاد بگیرید.

می‌توانید ابتدا مفاهیم اصلی دیتابیس و Queryهای پرکاربرد را یاد بگیرید و سپس هنگام کار روی پروژه‌های واقعی، SQL پیشرفته‌تر را به‌تدریج اضافه کنید.

چه بخش‌هایی از SQL فعلاً برای تستر ضروری نیست؟

یادگیری SQL می‌تواند بسیار گسترده باشد و اگر تستر بخواهد از همان ابتدا تمام قابلیت‌های SQL را یاد بگیرد، ممکن است زمان زیادی صرف موضوعاتی کند که در کار روزمره او کاربرد چندانی ندارند.

برای یک تستر، بهتر است ابتدا روی SQL موردنیاز برای تست و اعتبارسنجی داده‌ها تمرکز شود.

۱. Queryهای بسیار پیچیده

تستر در ابتدای مسیر معمولاً نیازی ندارد Queryهای بسیار پیچیده و چندلایه بنویسد.

مثلاً Queryهایی که شامل چندین JOIN، Subquery و منطق پیچیده باشند، می‌توانند در مراحل بعدی یاد گرفته شوند.

مهم‌تر این است که تستر ابتدا بتواند Queryهای ساده و قابل فهم بنویسد و نتیجه آن‌ها را درست تفسیر کند.

۲. Stored Procedureهای پیچیده

Stored Procedure مجموعه‌ای از دستورات SQL است که در Database ذخیره می‌شود و می‌تواند برای انجام عملیات مختلف اجرا شود.

EXEC GetUserOrders @UserId = 25;

تستر باید مفهوم Stored Procedure و کاربرد آن را بشناسد، مخصوصاً اگر پروژه از آن‌ها استفاده می‌کند؛ اما لزوماً لازم نیست در ابتدای مسیر در طراحی و توسعه Stored Procedureهای پیچیده متخصص باشد.

۳. Database Administration

موضوعاتی مانند:

  • مدیریت کاربران دیتابیس
  • Permissionها
  • Backup و Restore
  • Replication
  • Database Configuration
  • Monitoring
  • مدیریت منابع سرور

بیشتر در حوزه Database Administration قرار می‌گیرند.

تستر باید درک کلی مناسبی از این مفاهیم داشته باشد، اما این‌ها معمولاً جزو مهارت‌های اصلی یک Software Tester نیستند.

۴. بهینه‌سازی بسیار پیشرفته Query

تستر باید بداند که Queryهای سنگین می‌توانند روی Performance تأثیر بگذارند و با مفاهیمی مانند Index آشنا باشد.

اما در ابتدای مسیر لازم نیست در سطح متخصص Database Performance Optimization فعالیت کند.

مثلاً مفاهیمی مانند:

Execution Plan
Query Optimization
Index Tuning
Partitioning

می‌توانند در مراحل پیشرفته‌تر یاد گرفته شوند.

۵. قابلیت‌های تخصصی و وابسته به Database خاص

هر Database ممکن است قابلیت‌ها و Syntaxهای خاص خودش را داشته باشد.

مثلاً ممکن است پروژه‌ای از:

  • PostgreSQL
  • MySQL
  • SQL Server
  • Oracle

استفاده کند.

تستر بهتر است ابتدا مفاهیم عمومی SQL را یاد بگیرد و سپس اگر پروژه به Database خاصی نیاز داشت، ویژگی‌های مخصوص همان سیستم را یاد بگیرد.

پس روی چه چیزهایی تمرکز کنیم؟

برای یک تستر، مسیر یادگیری SQL می‌تواند تقریباً به این شکل باشد:

سطح اول؛ ضروری

SELECT
WHERE
AND / OR
ORDER BY
LIKE
IN
BETWEEN
IS NULL
COUNT
DISTINCT

سطح دوم؛ بسیار کاربردی

JOIN
GROUP BY
HAVING
INSERT
UPDATE
DELETE

سطح سوم؛ متناسب با پروژه

Subquery
CASE
UNION
CTE
Window Functions
Stored Procedures
Transactions

و در مراحل پیشرفته‌تر می‌توان سراغ موضوعاتی مانند Query Optimization و Performance Database رفت.

نکته کلیدی: هدف تستر از یادگیری SQL این نیست که تبدیل به متخصص دیتابیس شود.

هدف این است که بتواند داده‌ها را پیدا کند، روابط آن‌ها را بفهمد، نتیجه عملیات نرم‌افزار را اعتبارسنجی کند و در صورت مشاهده مشکل، اطلاعات دقیق‌تری برای تحلیل Bug در اختیار تیم قرار دهد.

Checklist تست دیتابیس برای تستر

داشتن یک Checklist می‌تواند به تستر کمک کند تا هنگام بررسی دیتابیس، موارد مهم را فراموش نکند. این Checklist قرار نیست جایگزین Test Case شود؛ بلکه می‌تواند به‌عنوان یک راهنمای سریع هنگام اجرای تست‌ها استفاده شود.

۱. بررسی ساختار داده‌ها

ابتدا باید مطمئن شویم ساختار دیتابیس با نیازمندی‌های سیستم مطابقت دارد.

  • آیا Tableهای موردنیاز وجود دارند؟
  • آیا Columnهای موردنیاز وجود دارند؟
  • آیا نوع داده‌ها مناسب است؟
  • آیا Primary Key به‌درستی تعریف شده است؟
  • آیا Foreign Keyهای موردنیاز وجود دارند؟
  • آیا Relationship بین Tableها صحیح است؟

۲. بررسی داده‌های ایجادشده

بعد از انجام یک عملیات در UI یا API، بررسی کنیم:

  • آیا رکورد موردنظر ایجاد شده است؟
  • آیا مقدار تمام Fieldها صحیح است؟
  • آیا مقدار پیش‌فرض درست اعمال شده است؟
  • آیا رکورد تکراری ایجاد نشده است؟
  • آیا مقدار NULL مطابق Requirement است؟

مثلاً بعد از ثبت کاربر:

SELECT
    id,
    name,
    email,
    status
FROM users
WHERE email = 'test@example.com';

۳. بررسی Update

هنگام تغییر اطلاعات بررسی کنیم:

  • آیا مقدار جدید ذخیره شده است؟
  • آیا مقدار قدیمی به‌درستی جایگزین شده است؟
  • آیا فقط رکورد موردنظر تغییر کرده است؟
  • آیا سایر داده‌های مرتبط تحت تأثیر قرار گرفته‌اند؟
  • آیا تغییر وضعیت مطابق Business Rule انجام شده است؟

۴. بررسی Delete

هنگام حذف داده بررسی کنیم:

  • آیا رکورد واقعاً حذف شده است؟
  • آیا سیستم از Soft Delete استفاده می‌کند؟
  • آیا رکوردهای مرتبط باید حذف شوند؟
  • آیا حذف یک رکورد باعث ایجاد داده‌های بدون مرجع می‌شود؟
  • آیا رفتار سیستم مطابق Requirement است؟

۵. بررسی Relationshipها

برای Relationship بین Tableها بررسی کنیم:

  • آیا Foreign Key به رکورد معتبر اشاره می‌کند؟
  • آیا Orphan Record وجود دارد؟
  • آیا رابطه One-to-One یا One-to-Many درست عمل می‌کند؟
  • آیا رکوردها به Entity درست متصل شده‌اند؟

مثلاً برای پیدا کردن سفارش‌هایی که کاربر معتبر ندارند:

SELECT orders.id, orders.user_id
FROM orders
LEFT JOIN users
    ON orders.user_id = users.id
WHERE users.id IS NULL;

۶. بررسی Data Integrity

در این مرحله باید بررسی کنیم داده‌ها از نظر منطقی و ساختاری معتبر هستند.

مواردی مانند:

  • Duplicate Data
  • مقدار NULL غیرمنتظره
  • Foreign Key نامعتبر
  • مقدار خارج از محدوده
  • داده ناسازگار بین Tableها
  • نقض Constraintها

می‌توانند نشانه وجود مشکل باشند.

۷. بررسی داده‌های مرزی و نامعتبر

فقط داده‌های معمولی را تست نکنید.

بسته به Requirement، موارد زیر نیز باید بررسی شوند:

Minimum Value
Maximum Value
Minimum - 1
Maximum + 1
NULL
Empty Value
Duplicate Value
Invalid Format

این کار می‌تواند بسیاری از خطاهای Business Logic را آشکار کند.

۸. بررسی هماهنگی UI، API و Database

در سیستم‌های چندلایه می‌توان یک عملیات را در مسیر زیر بررسی کرد:

UI
 ↓
API
 ↓
Backend
 ↓
Database

مثلاً بعد از ثبت سفارش:

  • UI چه چیزی نمایش می‌دهد؟
  • API چه Responseای برمی‌گرداند؟
  • Database چه داده‌ای ذخیره کرده است؟

اگر این سه بخش با یکدیگر سازگار نباشند، تستر اطلاعات بیشتری برای پیدا کردن محل مشکل خواهد داشت.

یک Checklist کوتاه برای استفاده روزمره

☐ ساختار Tableها صحیح است
☐ Primary Key صحیح است
☐ Foreign Keyها صحیح هستند
☐ داده جدید درست ایجاد شده است
☐ داده Update شده صحیح است
☐ Delete مطابق Requirement انجام شده است
☐ Duplicate Data وجود ندارد
☐ NULLها مطابق Requirement هستند
☐ Relationshipها صحیح هستند
☐ داده‌های مرزی بررسی شده‌اند
☐ داده‌های نامعتبر بررسی شده‌اند
☐ UI و API با Database سازگار هستند
☐ Test Data مناسب استفاده شده است
☐ داده‌های تست پس از اجرا مدیریت/پاک‌سازی شده‌اند

این Checklist را می‌توان در پروژه‌های مختلف متناسب با نوع سیستم، Database و Requirementها تغییر داد.

جمع‌بندی؛ تستر برای تست دیتابیس چه چیزهایی باید بداند؟

تست دیتابیس یکی از مهارت‌هایی است که می‌تواند دید تستر را از سطح رابط کاربری و رفتار ظاهری سیستم فراتر ببرد.

در یک نرم‌افزار، ممکن است کاربر فقط یک فرم، دکمه یا پیام موفقیت را ببیند؛ اما پشت همین عملیات، داده‌هایی ایجاد، تغییر یا حذف می‌شوند و بین چندین جدول ارتباط برقرار می‌شود.

یک تستر باید بتواند این داده‌ها را بررسی و اعتبارسنجی کند.

مهم‌ترین مهارت‌های یک تستر در تست دیتابیس

در این مقاله با مفاهیم مختلفی آشنا شدیم که مهم‌ترین آن‌ها عبارت‌اند از:

مفاهیم پایه دیتابیس

  • Database
  • Table
  • Row
  • Column
  • Primary Key
  • Foreign Key
  • Constraint
  • Relationship

SQLهای ضروری

  • SELECT
  • WHERE
  • ORDER BY
  • LIKE
  • IN
  • BETWEEN
  • COUNT
  • JOIN
  • GROUP BY
  • HAVING
  • INSERT
  • UPDATE
  • DELETE

مهارت‌های تستی

  • بررسی Data Integrity
  • پیدا کردن Duplicate Data
  • بررسی NULL
  • بررسی Relationship بین جداول
  • اعتبارسنجی Test Data
  • بررسی داده‌های مرزی و نامعتبر
  • مقایسه نتیجه UI و API با Database

آیا همه تسترها باید SQL حرفه‌ای بلد باشند؟

خیر.

اما یک تستر حرفه‌ای باید بتواند به کمک SQL سؤال‌های تستی خود را از دیتابیس بپرسد.

مثلاً:

آیا این کاربر واقعاً ایجاد شده است؟

SELECT *
FROM users
WHERE email = 'test@example.com';

یا:

آیا این کاربر سفارشی دارد؟

SELECT
    users.name,
    COUNT(orders.id) AS order_count
FROM users
LEFT JOIN orders
    ON users.id = orders.user_id
WHERE users.id = 25
GROUP BY users.id, users.name;

یا:

آیا ایمیل تکراری در دیتابیس وجود دارد؟

SELECT
    email,
    COUNT(*) AS count
FROM users
GROUP BY email
HAVING COUNT(*) > 1;

این نوع Queryها نشان می‌دهند که SQL برای تستر بیشتر از آنکه یک مهارت صرفاً برنامه‌نویسی باشد، ابزاری برای بررسی و اعتبارسنجی رفتار نرم‌افزار است.

در نهایت

تستر لازم نیست Database Administrator باشد؛ اما باید بتواند ساختار دیتابیس را بفهمد، داده‌ها را بررسی کند، روابط بین آن‌ها را تشخیص دهد و در صورت نیاز با SQL شواهد دقیق‌تری برای تأیید یا رد یک رفتار نرم‌افزار به دست آورد.

به همین دلیل، یادگیری SQL در کنار Manual Testing، API Testing و Automation Testing می‌تواند مهارت بسیار ارزشمندی برای یک Software Tester باشد.

منابع و مراجع

سؤالات متداول تست دیتابیس

تست دیتابیس چیست؟

تست دیتابیس فرایند بررسی صحت، کامل بودن، یکپارچگی و اعتبار داده‌هایی است که نرم‌افزار در دیتابیس ذخیره، تغییر یا بازیابی می‌کند.

چرا تستر باید دیتابیس را تست کند؟

چون موفقیت یک عملیات در UI یا API لزوماً به معنی صحیح بودن داده‌های ذخیره‌شده نیست. تستر می‌تواند با بررسی دیتابیس مطمئن شود داده‌ها، روابط بین جداول و قوانین مربوط به آن‌ها درست عمل می‌کنند.

آیا تستر باید SQL بلد باشد؟

بله، اما معمولاً نیازی نیست SQL را در سطح Database Developer یا Database Administrator بداند. برای شروع، تسلط بر Queryهایی مانند SELECT، WHERE، JOIN، COUNT، GROUP BY، HAVING و ORDER BY برای بسیاری از نیازهای تست کافی است.

مهم‌ترین دستورات SQL برای تستر کدام‌اند؟

از مهم‌ترین موارد می‌توان به SELECT، WHERE، AND / OR، ORDER BY، LIKE، IN، BETWEEN، COUNT، DISTINCT، JOIN، GROUP BY، HAVING، INSERT، UPDATE و DELETE اشاره کرد.

تفاوت Primary Key و Foreign Key چیست؟

Primary Key رکوردهای یک جدول را به‌صورت منحصربه‌فرد شناسایی می‌کند. Foreign Key برای ایجاد ارتباط بین یک جدول و جدول دیگر استفاده می‌شود. برای مثال، users.id می‌تواند Primary Key و orders.user_id می‌تواند Foreign Key باشد.

تستر چگونه داده‌های تکراری را پیدا می‌کند؟

می‌توان از GROUP BY و HAVING استفاده کرد:

SELECT email, COUNT(*) AS count
FROM users
GROUP BY email
HAVING COUNT(*) > 1;

این Query ایمیل‌هایی را که بیش از یک بار در جدول وجود دارند نمایش می‌دهد.

تفاوت NULL با مقدار خالی چیست؟

NULL به معنی نبودن یا نامشخص بودن مقدار است و با مقدار خالی ('')، صفر (0) یا false یکسان نیست. برای بررسی NULL باید از Syntax زیر استفاده کرد:

WHERE phone IS NULL

یا:

WHERE phone IS NOT NULL
JOIN در تست دیتابیس چه کاربردی دارد؟

JOIN به تستر اجازه می‌دهد داده‌های مرتبط از چند جدول را در یک Query بررسی کند. برای مثال، می‌توان با JOIN بررسی کرد که یک سفارش واقعاً متعلق به کدام کاربر است و ارتباط بین جداول به شکل صحیح برقرار شده است.

آیا تست دیتابیس فقط با SQL انجام می‌شود؟

خیر. SQL یکی از ابزارهای مهم تست دیتابیس است، اما تست دیتابیس می‌تواند شامل بررسی مواردی مانند Data Integrity، Constraints، Relationships، Stored Procedures، Triggers، Data Validation، Performance و Schema نیز باشد.

آیا باید بعد از هر تست UI دیتابیس را بررسی کنیم؟

خیر. بررسی مستقیم دیتابیس زمانی ارزش بیشتری دارد که صحت داده‌های Backend یا ذخیره‌سازی اطلاعات بخشی از هدف تست باشد. برای مثال، بعد از ثبت سفارش، تغییر وضعیت سفارش یا ایجاد حساب کاربری، بررسی دیتابیس می‌تواند اطلاعات ارزشمندی در اختیار تستر قرار دهد.

آیا تستر می‌تواند از INSERT، UPDATE و DELETE استفاده کند؟

بله، مخصوصاً در محیط‌های تست برای آماده‌سازی یا پاک‌سازی Test Data. اما این دستورات باید با احتیاط استفاده شوند و اجرای آن‌ها روی Production بدون مجوز و کنترل می‌تواند بسیار خطرناک باشد.

آیا تستر باید Database Administrator باشد؟

خیر. تستر باید دانش کافی برای درک ساختار دیتابیس، بررسی داده‌ها، اجرای Queryهای موردنیاز و تشخیص مشکلات داده‌ای داشته باشد؛ اما مدیریت زیرساخت دیتابیس معمولاً وظیفه Database Administrator یا تیم مربوط به Database است.

آیا تست دیتابیس برای Automation Tester مهم است؟

بله. در Automation Testing می‌توان نتیجه عملیات UI یا API را با داده ذخیره‌شده در دیتابیس مقایسه کرد. به همین دلیل SQL و شناخت دیتابیس می‌تواند مهارت مفیدی برای Automation Tester باشد.

مهم‌ترین هدف تست دیتابیس چیست؟

هدف اصلی این است که مطمئن شویم داده‌های سیستم صحیح، کامل، سازگار و مطابق Requirement و Business Rules هستند و ارتباط بین داده‌ها نیز به شکل صحیح برقرار شده است.

طبقه بندی شده در:

تست نرم افزار,

اخرین بروزرسانی: شهریور 23, 1405