database সফটওয কিভাবে ইউনিট ডেটাবেস প্রশ্নের সাথে একটি বস্তু পরীক্ষা




রিলেশনাল ডাটাবেজ কি (11)

আমি প্রথম পোস্টের সাথে একমত - ডেটাবেস অ্যাক্সেসটি একটি ইন্টারফেস প্রয়োগকারী একটি DAO লেয়ারে সরানো উচিত। তারপরে, আপনি DAO লেয়ারের স্টাব বাস্তবায়নের বিরুদ্ধে আপনার যুক্তি পরীক্ষা করতে পারেন।

আমি শুনেছি যে ইউনিট পরীক্ষার "পুরোপুরি সন্ত্রস্ত", "সত্যিই দুর্দান্ত" এবং "ভাল জিনিসগুলির সমস্ত উপায়ে" কিন্তু আমার ফাইলগুলির 70% বা তার বেশি ডেটাবেস ডাটাবেস অ্যাক্সেস (কিছু পড়া এবং কিছু লেখার) শোনা এবং আমি নিশ্চিত নই কিভাবে এই ফাইলগুলির জন্য একটি ইউনিট পরীক্ষা লিখতে।

আমি পিএইচপি এবং পাইথন ব্যবহার করছি কিন্তু আমি মনে করি এটি একটি প্রশ্ন যা ডেটাবেস অ্যাক্সেস ব্যবহার করে বেশিরভাগ / সমস্ত ভাষাতে প্রযোজ্য।


আপনার বিকল্প আছে:

  • একটি স্ক্রিপ্ট লিখুন যা আপনি ইউনিট পরীক্ষা শুরু করার আগে ডাটাবেসটি নিশ্চিহ্ন করে ফেলবেন, তারপরে ডেটা পূর্বনির্ধারিত সেটের সাথে ডিবি তৈরি করুন এবং পরীক্ষা চালান। আপনি প্রতিটি পরীক্ষা করার আগে এটি করতে পারেন - এটি ধীর হবে, কিন্তু কম ত্রুটি প্রবণ।
  • ডাটাবেস ইনজেকশন। (ছদ্ম-জাভা উদাহরণ, কিন্তু সমস্ত OO- ভাষাতে প্রযোজ্য)

    class Database {
     public Result query(String query) {... real db here ...}
    }

    class MockDatabase extends Database { public Result query(String query) { return "mock result"; } }

    class ObjectThatUsesDB { public ObjectThatUsesDB(Database db) { this.database = db; } }

    এখন উত্পাদনতে আপনি স্বাভাবিক ডাটাবেস ব্যবহার করেন এবং সমস্ত পরীক্ষার জন্য আপনি কেবল মক ডাটাবেসটি ইনজেকশন করেন যা আপনি বিজ্ঞাপন তৈরি করতে পারেন।

  • সর্বাধিক কোড জুড়ে ডিবি ব্যবহার করবেন না (এটি যে কোনও খারাপ অভ্যাস)। একটি "ডাটাবেস" অবজেক্ট তৈরি করুন যা ফলাফলগুলির সাথে ফিরে যাওয়ার পরিবর্তে স্বাভাবিক বস্তুগুলি ফেরত দেবে (অর্থাত টুপি {name: "marcin", password: "blah"} পরিবর্তে User ফেরত দেবে) আপনার সমস্ত পরীক্ষাগুলি এড হক তৈরি করা প্রকৃত বস্তুগুলির সাথে লিখুন এবং এই রূপান্তর ঠিক আছে কাজ করে নিশ্চিত করে যে একটি ডাটাবেস উপর নির্ভর করে একটি বড় পরীক্ষা লিখুন।

অবশ্যই এই পন্থা পারস্পরিক একচেটিয়া নয় এবং আপনি প্রয়োজন হিসাবে মিশ্রিত এবং তাদের সাথে মেলে করতে পারেন।


আমি সাধারণত বস্তু পরীক্ষা (এবং ORM, যদি থাকে) মধ্যে আমার পরীক্ষা ভেঙ্গে চেষ্টা এবং ডিবি পরীক্ষা। আমি ডেটা অ্যাক্সেস কলগুলি উপহাস করে জিনিসগুলির বস্তুটি পরীক্ষা করে দেখি যখন আমি ডিবির সাথে বস্তুর মিথস্ক্রিয়াগুলি পরীক্ষা করে জিনিসগুলির ডিবি পাশ পরীক্ষা করি, যা আমার অভিজ্ঞতাতে সাধারণত মোটামুটি সীমিত।

আমি লেখার ইউনিট পরীক্ষার সাথে হতাশ হয়ে পড়ি যতক্ষণ না আমি তথ্য অ্যাক্সেসের অংশটি ঠকানোর শুরু করি তাই আমাকে পরীক্ষার ডিবি তৈরি করতে বা উড়ে পরীক্ষা ডেটা জেনারেট করতে হয় না। ডেটা মজাদার করে আপনি রান টাইম এ এটি তৈরি করতে পারেন এবং আপনার বস্তু জ্ঞাত ইনপুটগুলির সাথে সঠিকভাবে কাজ করে তা নিশ্চিত করুন।


আপনার প্রকল্পের উচ্চ সমাহার এবং জুড়ে আলগা coupling আছে যদি আপনার ডাটাবেস অ্যাক্সেস পরীক্ষার যথেষ্ট সহজ। এই ভাবে আপনি কেবলমাত্র প্রতিটি জিনিস পরীক্ষা করেই সবকিছু পরীক্ষা করে নিচ্ছেন এমন বিষয়গুলি পরীক্ষা করতে পারেন।

উদাহরণস্বরূপ, যদি আপনি আপনার ইউজার ইন্টারফেস ক্লাসটি পরীক্ষা করে পরীক্ষা করেন তবে আপনি যে পরীক্ষাগুলি লিখছেন তা শুধুমাত্র UI- এর ভিতরে যুক্তিটি যাচাই করার চেষ্টা করা উচিত, যে ফাংশনের পিছনে ব্যবসায়িক লজিক বা ডাটাবেস অ্যাকশন নয়।

যদি আপনি ইউনিটটি প্রকৃত ডাটাবেস অ্যাক্সেসটি পরীক্ষা করতে চান তবে আপনি আসলে একটি ইন্টিগ্রেশন পরীক্ষাটি শেষ করতে পারবেন, কারণ আপনি নেটওয়ার্ক স্ট্যাক এবং আপনার ডেটাবেস সার্ভারের উপর নির্ভরশীল হবেন তবে আপনি এটি যাচাই করতে পারেন যে আপনার এসকিউএল কোডটি আপনি কী করেছেন না।

ব্যক্তিগতভাবে আমার জন্য ইউনিট পরীক্ষার গোপন শক্তি এমন হয়েছে যে এটি আমাকে আমার অ্যাপ্লিকেশানগুলিকে অনেক উন্নত উপায়ে ডিজাইন করতে বাধ্য করে তুলতে পারে। কারণ এটি সত্যিই আমাকে "এই ফাংশন সবকিছু করতে হবে" মানসিকতা থেকে বিরতি সাহায্য।

দুঃখিত, পিএইচপি / পাইথনের জন্য আমার কোনও নির্দিষ্ট কোড উদাহরণ নেই, তবে যদি আপনি একটি .NET উদাহরণ দেখতে চান তবে আমার একটি post যা আমি এমন একটি কৌশল বর্ণনা করে যা আমি এই একই পরীক্ষার জন্য ব্যবহার করতাম।


ডাটাবেস অ্যাক্সেসের সাথে একটি বস্তু পরীক্ষা করার সবচেয়ে সহজ উপায় লেনদেনের স্কোপগুলি ব্যবহার করছে।

উদাহরণ স্বরূপ:

    [Test]
    [ExpectedException(typeof(NotFoundException))]
    public void DeleteAttendee() {

        using(TransactionScope scope = new TransactionScope()) {
            Attendee anAttendee = Attendee.Get(3);
            anAttendee.Delete();
            anAttendee.Save();

            //Try reloading. Instance should have been deleted.
            Attendee deletedAttendee = Attendee.Get(3);
        }
    }

এটি মূলত একটি লেনদেনের রোলব্যাকের মত ডেটাবেসের অবস্থাটিকে ফিরিয়ে দেবে, যাতে আপনি কোনও পার্শ্ব প্রতিক্রিয়া ব্যতীত পরীক্ষাটি চালাতে পারেন। আমরা বড় প্রকল্পে সফলভাবে এই পদ্ধতির ব্যবহার করেছি। আমাদের বিল্ডটি চালানোর জন্য কিছুটা সময় নেয় (15 মিনিট), তবে 1800 ইউনিট পরীক্ষা করার জন্য এটি ভয়ঙ্কর নয়। এছাড়াও, যদি বিল্ড সময় একটি উদ্বেগের বিষয় হয় তবে আপনি বিল্ড প্রসেসটি একাধিক বিল্ডের জন্য পরিবর্তন করতে পারেন, একটি নির্মাণের জন্য src, অন্যটি যা পরে ইউনিট পরীক্ষা, কোড বিশ্লেষণ, প্যাকেজিং ইত্যাদি পরিচালনা করে।


আমি পিএইচপি তে কখনোই এটি করতে পারিনি এবং আমি পাইথন ব্যবহার করি নি, তবে আপনি যা করতে চান তা ডাটাবেসের কলগুলি ঠকায়। এটি করার জন্য আপনি কিছু IoC বাস্তবায়ন করতে পারেন কিনা তৃতীয় পক্ষের সরঞ্জাম বা আপনি এটি পরিচালনা করেন, তবে আপনি ডাটাবেস কলারের কিছু মক সংস্করণ বাস্তবায়ন করতে পারেন যেখানে আপনি সেই জাল কলটির ফলাফল নিয়ন্ত্রণ করবেন।

আইওসি একটি সহজ ফর্ম শুধু ইন্টারফেস কোডিং দ্বারা সঞ্চালিত করা যেতে পারে। এটি আপনার কোডে কিছু ধরণের অবজেক্ট অভিযোজন দরকার যা আপনার কাজ করার ক্ষেত্রে এটি প্রযোজ্য না হতে পারে (আমি যা বলেছি তা হল পিএইচপি এবং পাইথন আপনার উল্লেখ।

আশা করি এটি সহায়ক, যদি অন্য কিছু না থাকে তবে এখন অনুসন্ধান করতে কিছু শর্ত আছে।


ইউনিট পরীক্ষা জন্য পরীক্ষা তথ্য সেট আপ করা একটি চ্যালেঞ্জ হতে পারে।

যখন এটি জাভাতে আসে, আপনি ইউনিট পরীক্ষার জন্য স্প্রিং API গুলি ব্যবহার করলে, আপনি একক স্তরের লেনদেনগুলি নিয়ন্ত্রণ করতে পারেন। অন্য কথায়, আপনি ইউনিট পরীক্ষা চালাতে পারবেন যা ডাটাবেস আপডেট / সন্নিবেশ / মুছে ফেলা এবং পরিবর্তনগুলি রোলব্যাক অন্তর্ভুক্ত করে। মৃত্যুদন্ডের শেষে আপনি ডাটাবেসটিতে সবকিছু রেখে যাবেন যেমনটি আপনি কার্যকর করার আগে এটি ছিল। আমার কাছে, এটি পেতে পারেন হিসাবে ভাল।


আদর্শভাবে, আপনার বস্তু অবিচলিত থাকা উচিত। উদাহরণস্বরূপ, আপনার "ডেটা অ্যাক্সেস লেয়ার" থাকা উচিত, যা আপনি অনুরোধ করবেন, যা বস্তুগুলি ফেরত দেবে। এই ভাবে, আপনি আপনার ইউনিট পরীক্ষা আউট যে অংশ ছেড়ে দিতে পারেন, বা বিচ্ছিন্নতা তাদের পরীক্ষা।

আপনার অবজেক্টগুলি আপনার ডেটা স্তরতে জোরালোভাবে সংযুক্ত থাকলে, যথাযথ ইউনিট পরীক্ষা করা কঠিন। ইউনিট পরীক্ষা প্রথম অংশ, "ইউনিট" হয়। সমস্ত ইউনিট বিচ্ছিন্নতা পরীক্ষা করা সম্ভব হবে।

আমার সি # প্রোজেক্টগুলিতে, আমি এনএইচবিবারনেটকে একটি সম্পূর্ণ পৃথক ডাটা স্তর দিয়ে ব্যবহার করি। আমার বস্তু মূল ডোমেন মডেলে বাস করে এবং আমার অ্যাপ্লিকেশন স্তর থেকে অ্যাক্সেস করা হয়। অ্যাপ্লিকেশন স্তর উভয় তথ্য স্তর এবং ডোমেন মডেল স্তর আলোচনা।

অ্যাপ্লিকেশন স্তর কখনও কখনও "ব্যবসা স্তর" বলা হয়।

আপনি যদি পিএইচপি ব্যবহার করেন তবে শুধুমাত্র ডাটা অ্যাক্সেসের জন্য ক্লাসগুলির একটি নির্দিষ্ট সেট তৈরি করুন। আপনার অবজেক্টগুলির কোনও ধারণা নেই যে তারা কীভাবে স্থির থাকে এবং আপনার অ্যাপ্লিকেশান ক্লাসগুলির মধ্যে দুটি আপলোড করে।

আরেকটি বিকল্প mocking / stubs ব্যবহার করা হবে।


আমরা আমাদের অভিজ্ঞতার একটি স্বাদ দিতে পারি যখন আমরা ইউনিট পরীক্ষা শুরু করতে শুরু করলাম আমাদের মধ্য-স্তর প্রক্রিয়া যা "ব্যবসায় লজিক" এসকিএলএল ক্রিয়াকলাপগুলির একটি টন অন্তর্ভুক্ত করে।

আমরা প্রথমে একটি বিমূর্তন স্তর তৈরি করেছি যা আমাদের কোনও যুক্তিসঙ্গত ডাটাবেস সংযোগে "স্লট ইন" করার অনুমতি দেয় (আমাদের ক্ষেত্রে, আমরা কেবল একটি একক ওডিবিসি-টাইপ সংযোগ সমর্থিত)।

একবার এই জায়গায় ছিল, তখন আমরা আমাদের কোডে এমন কিছু করতে সক্ষম হয়েছিলাম (আমরা সি ++ এ কাজ করি, তবে আমি নিশ্চিত যে আপনি ধারণাটি পান):

GetDatabase ()। ExecuteSQL ("Foo (Blah, Blah) মধ্যে প্রবেশ করুন")

স্বাভাবিক রান সময়তে, GetDatabase () কোনও বস্তুকে ফেরত দেবে যা আমাদের সমস্ত এসকিউএল (ক্যোয়ারীসহ) খাওয়াবে, সরাসরি ও ডাটাবেসের মাধ্যমে ওডিবিসি।

আমরা তখন মেমরি ডেটাবেসগুলি সন্ধান করতে শুরু করেছিলাম - দীর্ঘতর ভাবে সেরাটি এসকিউএলাইট বলে মনে হচ্ছে। ( http://www.sqlite.org/index.html )। সেট আপ এবং ব্যবহার করার জন্য এটি অসাধারণভাবে সহজ এবং আমাদেরকে সাবক্লাস এবং GDDatabase ()কে সরিয়ে দেওয়ার জন্য একটি ইন-মেমরি ডেটাবেসে ফরওয়ার্ড করার জন্য অনুমতি দেওয়া হয়েছে যা প্রতিটি পরীক্ষার জন্য তৈরি এবং ধ্বংস করা হয়েছিল।

আমরা এখনও এর প্রাথমিক পর্যায়ে রয়েছি, কিন্তু এটি এখনও ভাল দেখাচ্ছে, তবে আমাদের নিশ্চিত করতে হবে যে আমরা যেকোনো টেবিল তৈরি করেছি এবং পরীক্ষা ডেটা দিয়ে তাদের ভরাট করেছি - তবে আমরা তৈরি করে কিছুক্ষন এখানে কাজের চাপ কমানো করেছি সাহায্যকারীর একটি জেনেরিক সেট যা আমাদের জন্য এই সমস্ত কিছু করতে পারে।

সামগ্রিকভাবে, এটি আমাদের টিডিডি প্রক্রিয়ার সাথে প্রচুর পরিমাণে সাহায্য করেছে, কারণ কিছু বাগ সংশোধন করার জন্য কোনও নিরীহ পরিবর্তনগুলি মনে হচ্ছে সেগুলি আপনার সিস্টেমে অন্যান্য অঞ্চলে (সনাক্ত করা কঠিন) ক্ষেত্রে বেশ অদ্ভুত প্রভাব ফেলতে পারে - SQL / ডেটাবেসের প্রকৃতির কারণে।

স্পষ্টতই, আমাদের অভিজ্ঞতাগুলি সি ++ ডেভেলপমেন্ট পরিবেশের কাছাকাছি কেন্দ্রীভূত হয়েছে, তবে আমি নিশ্চিত যে আপনি সম্ভবত পিএইচপি / পাইথনের অধীনে অনুরূপ কিছু পেতে পারছেন।

আশাকরি এটা সাহায্য করবে.


আমি ডাটাবেস আপনার কল আউট mocking সুপারিশ করবে। মকগুলি মূলত এমন বস্তু যা আপনি কোনও পদ্ধতিতে কল করার চেষ্টা করছেন এমন বস্তুর মতো, এই অর্থে যে তাদের একই বৈশিষ্ট্য, পদ্ধতি ইত্যাদি রয়েছে যা কলারের জন্য উপলব্ধ। কিন্তু কোনও নির্দিষ্ট পদ্ধতি করার সময় তারা যে কোনও কর্ম সম্পাদন করার পরিবর্তে প্রোগ্রাম করার পরিবর্তে এটি সম্পূর্ণভাবে ছাড়ে এবং শুধুমাত্র একটি ফলাফল প্রদান করে। যে ফলাফল সাধারণত এগিয়ে আপনার দ্বারা সংজ্ঞায়িত করা হয়।

মকিংয়ের জন্য আপনার বস্তুগুলি সেট আপ করার জন্য, আপনাকে সম্ভবত নিম্নোক্ত ছদ্ম-কোডের মতো নিয়ন্ত্রণ / নির্ভরতা ইনজেকশন প্যাটার্নের কিছু ধরণের আনুষঙ্গিক ব্যবহার করতে হবে:

class Bar
{
    private FooDataProvider _dataProvider;

    public instantiate(FooDataProvider dataProvider) {
        _dataProvider = dataProvider;
    }

    public getAllFoos() {
        // instead of calling Foo.GetAll() here, we are introducing an extra layer of abstraction
        return _dataProvider.GetAllFoos();
    }
}

class FooDataProvider
{
    public Foo[] GetAllFoos() {
        return Foo.GetAll();
    }
}

এখন আপনার ইউনিট টেস্টে, আপনি FooDataProvider এর একটি কাহিনী তৈরি করেছেন যা আপনাকে ডেটাবেসকে আঘাত না করে GetAllFoos পদ্ধতিটি কল করার অনুমতি দেয়।

class BarTests
{
    public TestGetAllFoos() {
        // here we set up our mock FooDataProvider
        mockRepository = MockingFramework.new()
        mockFooDataProvider = mockRepository.CreateMockOfType(FooDataProvider);

        // create a new array of Foo objects
        testFooArray = new Foo[] {Foo.new(), Foo.new(), Foo.new()}

        // the next statement will cause testFooArray to be returned every time we call FooDAtaProvider.GetAllFoos,
        // instead of calling to the database and returning whatever is in there
        // ExpectCallTo and Returns are methods provided by our imaginary mocking framework
        ExpectCallTo(mockFooDataProvider.GetAllFoos).Returns(testFooArray)

        // now begins our actual unit test
        testBar = new Bar(mockFooDataProvider)
        baz = testBar.GetAllFoos()

        // baz should now equal the testFooArray object we created earlier
        Assert.AreEqual(3, baz.length)
    }
}

একটি সাধারণ mocking দৃশ্যকল্প, সংক্ষিপ্তভাবে। অবশ্যই আপনি এখনও ইউনিট আপনার প্রকৃত ডাটাবেস কল পরীক্ষা করতে চান, যার জন্য আপনি ডাটাবেস আঘাত করতে হবে।


এক্সুনিট টেস্ট প্যাটার্নস বইটি ডেটাবেসকে হিট করে এমন ইউনিট-পরীক্ষার কোডটি পরিচালনা করার কিছু উপায় বর্ণনা করে। আমি অন্যদের সাথে একমত যে বলছে যে আপনি এটি করতে চান না কারণ এটি ধীরে ধীরে, তবে আপনাকে এটি কিছুটা করতে হবে, IMO। উচ্চ স্তরের স্টাফ পরীক্ষা করার জন্য ডিবি সংযোগটি মজাদার করা একটি ভাল ধারণা, তবে প্রকৃত ডাটাবেসের সাথে যোগাযোগ করার জন্য আপনি যা করতে পারেন তার পরামর্শগুলির জন্য এই বইটি দেখুন।





unit-testing