وحدة اختبار نصوص قاعدة البيانات

بقبول سهولة استخدام اختبارات الوحدة على C ++ المفضلة ، حاولت نقل تجربتي إلى TSQL ، خاصة وأن صاحب العمل الجديد يحب مبادرة مفيدة محليًا ويوزع الكعك لها.

نظرت من خلال العديد من الأطر المعروفة جيدًا ، توصلت إلى استنتاج مفاده أنها ، كقاعدة عامة ، كبيرة الحجم وتحمل بناءًا إضافيًا يحتاج إلى دراسة إضافية.

تعمل بعض الأطر بشكل جميل وترضي عين المدير ، الذين تظهر لهم ، ولكن لديها عدد من القيود التي لم تعجبني.

كنت أرغب في تنفيذ كل شيء على TSQL نقي حلال حلال-أرثوذكسي.

من وقت لآخر يصرف الانتباه عن التطور الرئيسي لعدة سنوات على شحذ هيكل البرنامج النصي ، قررت مشاركته معك (ولكن لا يزال بإمكانك إنتاج 3.5 ميغابايت من البرامج النصية).

كانت المتطلبات الأساسية بالنسبة لي بسيطة - لا بد لي من إجراء أي اختبار للوحدة في ملف دون الحاجة إلى أي إيماءات وأدوات برامج خاصة - فقط المتشددين: sqlcmd أو MSSMS.

لا يتم إجراء أي تغييرات على قاعدة البيانات التي يتم إجراء الاختبار فيها - يتم إرجاع كل شيء إلى بداية البرنامج النصي.

فقط مجموعة واحدة من القيود - يجب أن يعمل الاختبار في قاعدة بيانات فارغة (قد تكون البيانات الأولية) ، وإلا فإنك تتعب من تفكيك جميع الخيارات.

المهمة الرئيسية هي اختبار المنطق والحفاظ على سلامة المنطق.

لهذا ، أضع العنوان التالي في بداية الاختبار:

SET QUOTED_IDENTIFIER ON GO PRINT '-------------------------------- CLR Unit tests for Habr Logic ---------------------------------' IF 0 < ( SELECT count(*) FROM device) begin RAISERROR ('FAILED: database must be empty for this unit test', 16, -1 ) end GO 

أحاول عدم إنشاء اختبارات الوحدة لفترة أطول من شاشتين ، على الرغم من أن هذا ليس سهلاً ، في حالة المنطق المعقد.

يشبه اختبار الوحدة النموذجي هذا ويتكون من 3 أجزاء رئيسية:

 BEGIN TRAN TestClr2 declare @test_name sysname = (select TOP 1 name from sys.dm_tran_active_transactions WHERE transaction_type = 1 ORDER BY transaction_begin_time DESC) + ' [fn_calculate_dev_status] record for device has wrong range' BEGIN TRY SET NOCOUNT ON; -- 1. prepare data for unit test insert into device (mli, oxygen, stamp ) values ('111', 5.55, getdate() ) -- 2. execute unit test -- SELECT dbo.fn_calculate_dev_status( 111, 0.1, 1.2) declare @result int = ( SELECT dbo.fn_calculate_dev_status( '111', 0.1, 1.2) ) END TRY BEGIN CATCH SELECT ERROR_NUMBER() AS ErrorNumber, ERROR_SEVERITY() AS ErrorSeverity, ERROR_STATE() AS ErrorState , @test_name AS ErrorProcedure, ERROR_LINE() AS ErrorLine, ERROR_MESSAGE() AS ErrorMessage END CATCH -- 3. result verification IF @result <> 0 RAISERROR ('FAILED: %s no data for device should be presented %d ', 16, -1, @test_name, @result ) ELSE print 'PASSED ' + @test_name ROLLBACK TRAN TestClr2 GO 

- 1. إعداد البيانات لاختبار الوحدة

هنا يمكننا ملء الجداول اللازمة بالبيانات وإعداد بعض المتغيرات أو الجداول المؤقتة حتى لا تفسد الشفرة في قسم الاختبار.

- 2. تنفيذ اختبار الوحدة

هنا ، كقاعدة ، يذهب إما استدعاء دالة أو إجراء أو تغيير جدول ، إذا اختبرنا منطق الزناد.

- 3. نتيجة التحقق

في هذا الجزء من الاختبار ، نتحقق من كيفية تغير حالة كائنات قاعدة البيانات ، أو نتيجة إجراء الوظائف المختبرة.

إذا أعادت وظيفة الإجراء سجلاً ، فإننا نضيفه إلى الجدول المؤقت ونحلله بالفعل.

تتم مقارنة النتائج المجمعة والمحضرة بالمعيار وترمي استثناء إذا فشل كل شيء آخر.

مع Oracle ، كل شيء أكثر تعقيدًا بعض الشيء - لم أستطع القيام بالكتابة وتشغيل الاختبار بهذا الشكل وفي نفس الإيديولوجية ، بدلاً من تجربة صغيرة - توقفنا عن دعم Oracle لمنتجنا.

يتم إصدار كل اختبار وحدة كإجراء:

 CREATE OR REPLACE PROCEDURE UnitTest9_TRG_JOBLOGDETAIL AS v_message VARCHAR2(255) := 'UnitTest9_TRG_JOBLOGDETAIL: INSERT joblogdetail]- joblogdetail_result not Failed and joblogdetail_endtime is null '; v_maxdate date := '2014/01/01'; v_cnt NUMBER := 0; BEGIN savepoint my_savepoint; <b>-- 1. prepare data for unit test</b> insert into device ( dev_datecreated, dev_create_user, dev_ipaddress, dev_serialnumber , dev_productid, dev_manufacturer, dev_model, dev_id, dev_status, dev_functions) values (sysdate, 'Joe', '1.127.0.1', 'GSN-6238-N34', 'PRTF-452', 'Pinter Company', 'CM6003', 1, 1, 1 ); insert into joblog (JOBLOG_ID, joblog_starttime, joblog_progress) values (11, sysdate, 1); insert into joblog_template (JOBLOG_TEMPLATE_ID, joblog_id, joblog_templatename, joblog_templatetype) values (111, 11, N'joblog_template_test', 1); <b>-- 2. execute unit test</b> insert into joblogdetail ( JOBLOGDETAIL_ID, joblog_template_id, joblogdetail_function, joblogdetail_functiondetail, joblogdetail_result, joblogdetail_dev_id, joblogdetail_starttime, joblogdetail_endtime) values ( 1111, 111, 1, 1, 40, 1, v_maxdate, v_maxdate); <b>-- 3. result verification</b> SELECT count(dev_id) INTO v_cnt FROM device where dev_last_comm_time = v_maxdate; IF 1 <> v_cnt THEN DBMS_OUTPUT.PUT_LINE( 'FAILED: ' || v_message || ': Should not be update dev_last_comm_time: ' || TO_CHAR(v_maxdate)); ELSE DBMS_OUTPUT.PUT_LINE( 'PASSED: ' || v_message ); END IF; rollback to my_savepoint; END; / 

في نفس ملف الاختبار في النهاية ، يجب عليك تنظيف قاعدة البيانات من الاختبارات التي تم إنشاؤها وتنفيذها.

 commit; / set serveroutput on; SET FEEDBACK OFF; spool C:\dist\test.spl; exec UnitTest_empty_database; exec UnitTest3297_TRGBFR_UDEVICE(1); exec UnitTest5_TRG_BF_UDEVICE; exec UnitTest_3062a; ... spool off; / DROP PROCEDURE UnitTest_3062; DROP PROCEDURE UnitTest_BIRDIESEC_3344; DROP PROCEDURE UnitTest_empty_database; ... SET FEEDBACK ON; commit; 

هذا كل شئ.

ثم أنت فقط تنتج الملفات ، مقسمة إلى فئات من النوع: المشغلات والوظائف والإجراءات والتقارير والكائنات الكبيرة والخاصة لمنطق الأعمال ، وبالطبع لكل كائن قاعدة بيانات.

تقريبا كل مطوري قواعد البيانات يتجهمون ويقولون - لماذا يجب أن أترك المختبرين يقومون بذلك. إذا كانت قاعدة البيانات لا تحتوي على منطق من الكلمة على الإطلاق ، فأنا أتفق معهم ، ولكن إذا كان هناك الكثير منها ، فمن الطبيعي أن ينقذوا الأعصاب والسمعة والمال.

مثال.

لدينا في واجهة الويب أشجار روابط منطقية بين كائنات الأشجار مثل أمريكا -> كندا -> أونتاريو -> واترلو ، آسيا -> اليابان -> طوكيو -> إيبينا ، أي كرة كاملة من المكاتب الجغرافية.

تحتوي كل عقدة على قواعد معقدة للغاية ، يقوم المستخدم أو القاعدة أو المولد بتعيين الأجهزة.

ونتيجة لذلك ، حتى التعليمات الموصوفة بالتفصيل في خطوات هدم الجميع ، حتى أولئك الذين شاركوا في مناقشة وتطوير هذا المنطق.

أكثر من خمسين خطوة من التعليمات مع مجموعات بيانات مختلفة - يتم توثيق كل شيء بالتفصيل.

أي تغيير أو إضافة إلى المنطق هو ساعة من التحقق اليدوي التي لم يكسرها شيء.
إعادة هيكلة الموت مماثلة.

بعد أن غطيت المنطق باختبارات الوحدة ، يتم فحص كل شيء بالحرير وأنا متأكد من أن كل شيء يعمل كما ينبغي.

أي مطور جافا يلجأ إلي ، ويرمي الرعد والبرق (التفكير في نفسه حول يدي ملتوية) يتم وضعه بسهولة عن طريق تشغيل الاختبار المناسب.

بضع دقائق والجميع راضون. سيتم إبلاغ أي تغيير فادح في الرمز في غيابي بسرعة عن طريق البريد.

بطبيعة الحال ، كشخص كسول ، قررت أتمتة كل شيء من أجل الأتمتة المستمرة وكتبت العصيدة من الدفعات والثعبان.

أطلب منك أن تنفذ قليلاً ، في التطوير اليومي لما يقرب من اثني عشر لغة وبيئات عليك أن تقفز بينها ، هناك نقص كبير في الوقت في لعق كل شيء ووضعه في مظهر احترافي.

لم أكن أرغب في القيام بكل شيء على windows powerhell - لا تزال تخطيطاتنا تعمل هنا وهناك على windows95 المضمّن.

كنت أرغب في إجراء جميع المكالمات في Python ، ولكن اتضح أن بعض تراكيب sql (تحليل XML داخل cte) غير مدعومة ليس فقط في مكتبة python ، ولكن أيضًا في .NET ، لذلك فعلت البرمجة النصية من خلال sqlcmd.

تم نشر الرمز هنا .

لتشغيل مثال عملي ، ما عليك سوى تعديل ملفين: smtppart.py و config.ini - اسم خادم SMTP والمنفذ والبريد الإلكتروني حيث سيتم إسقاط رسائل الخطأ.

تحاول النصوص البرمجية أولاً الحصول على آخر التحديثات من svn (استبدلها بنفسك - git ، perforce ، ...).

ثم يتم إنشاء قاعدة نظيفة من البرامج النصية باسم عشوائي ، ويتم تشغيل اختبارات الوحدة فيه ، ثم يتم حذف القاعدة.

يتم إنشاء قاعدة بيانات تحتوي على 80 ميجا بايت من البرامج النصية واختبارات 3.5 ميجا بايت (تم إجراء الجزء الرئيسي من النظام بالفعل قبل أن انضممت إلى الشركة ، لذلك اختبرت الجزء الخاص بي فقط) على جهازي في حوالي 15 دقيقة. لدي الوقت لشرب فنجان من القهوة قبل الالتزام النهائي.

إذا كانت هناك أخطاء ، فسيتم إرسال نتائج الخطأ إلى البريد الإلكتروني.

يتم وصف تثبيت التبعية في الملف: readme.txt

بعد كل تغيير للرمز ، يجب عليك تعيين تجزئة الرمز يدويًا (ستظهر في سطر الأوامر) في ملف config.ini - ستظهر الرسالة حتى إذا تم تغيير الرمز ولم يتم كسر أي شيء - حتى أتمكن من التحكم في التغييرات في الرمز حتى أتمكن من التحقق من التغييرات دون مشاركتي السابقة.



يمكن وضع إطلاق جميع اختبارات الوحدة في ملف autorun.bat في برنامج جدولة مهام Windows لتشغيله 1-2 قبل يوم واحد من بناء الشركة أو بعد مغادرة المنزل - إذا حدث شيء في المساء - يمكنك الاطلاع على ما حدث أمام التلفزيون وإصلاحه بسرعة.

أعلم أنه في اختبارات الوحدة يكون من الصعب إعداد كل شيء ، ومن ثم يكون من السهل والممتع كتابة الاختبارات ، على الرغم من أن ذلك قد يكون صعبًا وصعبًا ، ولكنه ضروري. بالتوفيق في الاختبار ، آمل أن تساعد نصيحتي شخصًا ما.

سأكون سعيدًا لأخذ النصيحة إذا كان هناك شيء يمكن تحسينه في مكان ما وتمشيط الرمز ، فلا تحكم بدقة.

Source: https://habr.com/ru/post/ar417569/


All Articles