সত্তা ফ্রেমওয়ার্ক 6 দিয়ে লোক ইউনিট কীভাবে পরীক্ষা করছে, আপনার কি বিরক্ত করা উচিত?


170

আমি কেবল ইউনিট টেস্টিং এবং সাধারণভাবে টিডিডি দিয়ে শুরু করছি। আমি আগে ছুঁড়েছি তবে এখন আমি এটিকে আমার কর্মপ্রবাহে যুক্ত করতে এবং আরও ভাল সফ্টওয়্যার লেখার জন্য দৃ determined় প্রতিজ্ঞ।

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

ইস্যুটি হ'ল আমি ইতিমধ্যে নিজেকে অবরুদ্ধ করে রেখেছি কারণ আমি কোনও সংগ্রহশালায় EF দূরে রাখতে চাইনি (এটি এখনও নির্দিষ্ট প্রশ্নের জন্য পরিষেবাদির বাইরে পাওয়া যাবে) এবং আমার পরিষেবাগুলি পরীক্ষা করতে চাই (EF প্রসঙ্গটি ব্যবহৃত হবে) ।

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

আমি কোডটি যাচাই করতে চাই তা দেখতে খুব সহজ। (আমি কী করছি তা বোঝার এবং বোঝার জন্য এটি কেবল ডামি কোড, আমি টিডিডি ব্যবহার করে তৈরি করতে চাই)

প্রসঙ্গ

public interface IContext
{
    IDbSet<Product> Products { get; set; }
    IDbSet<Category> Categories { get; set; }
    int SaveChanges();
}

public class DataContext : DbContext, IContext
{
    public IDbSet<Product> Products { get; set; }
    public IDbSet<Category> Categories { get; set; }

    public DataContext(string connectionString)
                : base(connectionString)
    {

    }
}

সেবা

public class ProductService : IProductService
{
    private IContext _context;

    public ProductService(IContext dbContext)
    {
        _context = dbContext;
    }

    public IEnumerable<Product> GetAll()
    {
        var query = from p in _context.Products
                    select p;

        return query;
    }
}

বর্তমানে আমি কয়েকটি জিনিস করার মানসিকতায় আছি:

  1. এই পদ্ধতির মতো কোনও কিছুর সাথে EF প্রসঙ্গকে উপহাস করা- EF উপহাস করা যখন ইউনিট পরীক্ষা করা হয় বা moq এর মতো ইন্টারফেসে সরাসরি উপহাসের কাঠামো ব্যবহার করা হয় - ইউনিট পরীক্ষাগুলি যে ব্যথা করতে পারে সে ব্যথা গ্রহণ করা তবে অগত্যা ইন্টিগ্রেশন টেস্টগুলি শেষ করে শেষ করার জন্য কাজ করা উচিত নয়?
  2. হয়তো ভালো কিছু ব্যবহার প্রচেষ্টা উপহাস মতিন করুন - আমি এটা ব্যবহার না এবং নিশ্চিত অন্য কেউ বন্য এটা ব্যবহার করছে যদি না?
  3. যে কোনও কিছু যা কেবল ইএফ-তে ফিরে কল করে তা পরীক্ষা করে বিরক্ত করবেন না - অতএব মূলত পরিষেবা পদ্ধতিগুলি যা সরাসরি EF- কে কল করে (getAll ইত্যাদি) ইউনিট পরীক্ষা করা হয় না তবে কেবল ইন্টিগ্রেশন পরীক্ষিত হয়?

বাইরে যে কেউ এখানে সত্যই কোনও রেपो ছাড়াই করছে এবং সাফল্য পাচ্ছে?


আরে মোডিকা, আমি সম্প্রতি এটি সম্পর্কে চিন্তাভাবনা করছিলাম (এই প্রশ্নের কারণে: stackoverflow.com/questions/25977388/… ) এতে আমি এই মুহুর্তে কীভাবে কাজ করব তা আরও কিছুটা আনুষ্ঠানিকভাবে বর্ণনা করার চেষ্টা করেছি, তবে আমি শুনতে শুনতে খুব পছন্দ করব আপনি এটা করছেন।
সামি

হাই @ সামি, আমরা যেভাবে এটি করার সিদ্ধান্ত নিয়েছি তা ইউনিট টেস্ট কিছুই ছিল না যা সরাসরি ইএফকে স্পর্শ করেছিল। প্রশ্নগুলি পরীক্ষা করা হয়েছিল তবে ইউনিট টেস্ট নয়, ইন্টিগ্রেশন টেস্ট হিসাবে। মেকিং ইএফকে কিছুটা নোংরা লাগছে, তবে এই প্রকল্পটি ছোট ছিল তাই ডাটাবেস হিট করার জন্য প্রচুর পরিমাণে পরীক্ষা করার পারফরম্যান্স প্রভাবটি আসলেই উদ্বেগের বিষয় ছিল না তাই আমরা এটি সম্পর্কে আরও কিছুটা বাস্তববাদী হতে পারি। আমি এখনও আপনার সাথে পুরোপুরি সত্যবাদী হওয়ার জন্য সর্বোত্তম পদ্ধতির কী তা 100% নিশ্চিত নই, কোনও এক সময় আপনি EF- এ আঘাত করতে চলেছেন (এবং আপনার ডিবি) এবং ইউনিট পরীক্ষার বিষয়টি এখানে আমার কাছে সঠিক মনে হয় না।
মোডিকা

উত্তর:


186

এটি এমন একটি বিষয় যা আমি খুব আগ্রহী There এমন অনেক পিউরিস্ট রয়েছে যারা বলে যে আপনার EF এবং NHibernate এর মতো প্রযুক্তি পরীক্ষা করা উচিত নয়। তারা ঠিক আছে, তারা ইতিমধ্যে খুব কঠোরভাবে পরীক্ষা করা হয়েছে এবং পূর্ববর্তী উত্তর হিসাবে বলা হয়েছে যে আপনার নিজের কী নয় তা পরীক্ষার জন্য প্রচুর পরিমাণে ব্যয় করা প্রায়শই অর্থহীন।

তবে, আপনি নীচে ডাটাবেস নিজস্ব! এখানেই আমার মতে এই পন্থাটি ভেঙে যায়, আপনার পরীক্ষা করার দরকার নেই যে EF / NH তাদের কাজগুলি সঠিকভাবে করছে। আপনার ম্যাপিং / প্রয়োগগুলি আপনার ডাটাবেসের সাথে কাজ করছে তা পরীক্ষা করা দরকার। আমার মতে এটি আপনি পরীক্ষা করতে পারেন এমন একটি সিস্টেমের অন্যতম গুরুত্বপূর্ণ অঙ্গ।

কড়া কথায় বলতে গেলে আমরা ইউনিট পরীক্ষার ডোমেন থেকে বের হয়ে ইন্টিগ্রেশন টেস্টিংয়ে চলেছি কিন্তু নীতিগুলি একই রয়েছে remain

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

এখানে কয়েকটি বিষয় বিবেচনা করতে হবে:

  1. আপনার ডাটাবেস প্রতিটি পরীক্ষার সাথে একটি পরিচিত অবস্থায় থাকা প্রয়োজন। বেশিরভাগ সিস্টেমই হয় ব্যাকআপ ব্যবহার করে বা এর জন্য স্ক্রিপ্ট তৈরি করে।
  2. প্রতিটি পরীক্ষা অবশ্যই পুনরাবৃত্তিযোগ্য
  3. প্রতিটি পরীক্ষা অবশ্যই পারমাণবিক হতে হবে

আপনার ডাটাবেস সেট আপ করার জন্য দুটি প্রধান পন্থা রয়েছে, প্রথমটি হ'ল ইউনিটেষ্ট টেস্ট চালনা ডিবি স্ক্রিপ্ট। এটি নিশ্চিত করে যে আপনার ইউনিট পরীক্ষার ডাটাবেস সবসময় প্রতিটি পরীক্ষার শুরুতে একই অবস্থায় থাকবে (আপনি এটি পুনরায় সেট করতে পারেন বা এটি নিশ্চিত করতে প্রতিটি পরীক্ষা লেনদেনে চালাতে পারেন)।

আপনার অন্য বিকল্পটি আমি যা করি তা প্রতিটি স্বতন্ত্র পরীক্ষার জন্য নির্দিষ্ট সেটআপগুলি চালান। আমি বিশ্বাস করি যে এটি দুটি প্রধান কারণে সেরা পন্থা:

  • আপনার ডাটাবেসটি সহজ, প্রতিটি পরীক্ষার জন্য আপনার পুরো স্কিমার প্রয়োজন হয় না
  • প্রতিটি পরীক্ষাটি নিরাপদ, যদি আপনি আপনার তৈরি স্ক্রিপ্টের একটি মান পরিবর্তন করেন তবে এটি কয়েক ডজন অন্যান্য পরীক্ষাকে অবৈধ করে না।

দুর্ভাগ্যক্রমে আপনার আপস এখানে গতি। এই সমস্ত পরীক্ষা চালাতে, এই সমস্ত সেটআপ চালাতে / স্ক্র্যাপগুলি ছিঁড়ে ফেলতে সময় লাগে।

একটি চূড়ান্ত বিষয়, আপনার ওআরএম পরীক্ষার জন্য এত বড় এসকিউএল লিখতে খুব কঠোর পরিশ্রম হতে পারে। আমি এখানে খুব বাজে দৃষ্টিভঙ্গি গ্রহণ করি (এখানকার পিউরিস্টরা আমার সাথে একমত নন) আমি আমার পরীক্ষা তৈরি করতে আমার ওআরএম ব্যবহার করি! আমার সিস্টেমে প্রতিটি ডএল পরীক্ষার জন্য আলাদা স্ক্রিপ্ট না করে আমার একটি পরীক্ষা সেটআপ পর্ব রয়েছে যা বস্তুগুলি তৈরি করে, তাদের প্রসঙ্গে সংযুক্ত করে সংরক্ষণ করে। আমি তখন আমার পরীক্ষা চালাতে।

এটি আদর্শ সমাধান থেকে অনেক দূরে তবে বাস্তবে আমি দেখতে পেলাম যে এটি পরিচালনা করা খুব সহজ (বিশেষত যখন আপনার কয়েক হাজার পরীক্ষা রয়েছে), অন্যথায় আপনি প্রচুর স্ক্রিপ্ট তৈরি করছেন। বিশুদ্ধতার উপর ব্যবহারিকতা।

আমি নিঃসন্দেহে কয়েক বছর (মাস / দিন) এই উত্তরটি ফিরে ফিরে দেখব এবং আমার দৃষ্টিভঙ্গি পরিবর্তিত হওয়ায় নিজের সাথে একমত নই - তবে এটি আমার বর্তমান পদ্ধতি is

এটির উপরে আমি যা বলেছি সবগুলি চেষ্টা করার চেষ্টা করা এবং এটি আমার সাধারণ ডিবি ইন্টিগ্রেশন পরীক্ষা:

[Test]
public void LoadUser()
{
  this.RunTest(session => // the NH/EF session to attach the objects to
  {
    var user = new UserAccount("Mr", "Joe", "Bloggs");
    session.Save(user);
    return user.UserID;
  }, id => // the ID of the entity we need to load
  {
     var user = LoadMyUser(id); // load the entity
     Assert.AreEqual("Mr", user.Title); // test your properties
     Assert.AreEqual("Joe", user.Firstname);
     Assert.AreEqual("Bloggs", user.Lastname);
  }
}

এখানে লক্ষ্য করার মূল বিষয়টি হ'ল দুটি লুপের সেশনগুলি সম্পূর্ণ স্বাধীন। রানটেষ্টের প্রয়োগের ক্ষেত্রে আপনাকে অবশ্যই নিশ্চিত করতে হবে যে প্রসঙ্গটি প্রতিশ্রুতিবদ্ধ এবং ধ্বংস হয়েছে এবং আপনার ডেটা কেবলমাত্র দ্বিতীয় অংশের জন্য আপনার ডাটাবেস থেকে আসতে পারে।

13/10/2014 সম্পাদনা করুন

আমি বলেছিলাম যে আমি সম্ভবত আগামী মাসগুলিতে এই মডেলটি সংশোধন করব। আমি যখন উচ্চতরভাবে আমার পক্ষে মতামতটির পক্ষে দাঁড়িয়েছি তখন আমি আমার পরীক্ষার ব্যবস্থাটি কিছুটা আপডেট করেছি। আমি এখন টেস্টসেটআপ এবং টেস্টটিয়ারডাউনে সত্ত্বা তৈরি করার ঝোঁক।

[SetUp]
public void Setup()
{
  this.SetupTest(session => // the NH/EF session to attach the objects to
  {
    var user = new UserAccount("Mr", "Joe", "Bloggs");
    session.Save(user);
    this.UserID =  user.UserID;
  });
}

[TearDown]
public void TearDown()
{
   this.TearDownDatabase();
}

তারপরে প্রতিটি সম্পত্তি পৃথকভাবে পরীক্ষা করুন

[Test]
public void TestTitle()
{
     var user = LoadMyUser(this.UserID); // load the entity
     Assert.AreEqual("Mr", user.Title);
}

[Test]
public void TestFirstname()
{
     var user = LoadMyUser(this.UserID);
     Assert.AreEqual("Joe", user.Firstname);
}

[Test]
public void TestLastname()
{
     var user = LoadMyUser(this.UserID);
     Assert.AreEqual("Bloggs", user.Lastname);
}

এই পদ্ধতির বিভিন্ন কারণ রয়েছে:

  • কোনও অতিরিক্ত ডাটাবেস কল নেই (একটি সেটআপ, একটি টিয়ারডাউন)
  • পরীক্ষাগুলি অনেক বেশি দানাদার, প্রতিটি পরীক্ষার একটি সম্পত্তি যাচাই করে
  • সেটআপ / টিয়ারডাউন যুক্তি নিজেই টেস্ট পদ্ধতি থেকে সরানো হয়

আমি মনে করি এটি পরীক্ষার ক্লাসকে আরও সহজ করে তোলে এবং পরীক্ষাগুলি আরও দানাদার ( একক জমিদারি ভাল )

5/3/2015 সম্পাদনা করুন

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

এটির সাহায্যে আমার এখন দুটি বেস ক্লাস SetupPerTestএবং আছে SingleSetup। এই দুটি শ্রেণি প্রয়োজনীয় কাঠামোটি প্রকাশ করে।

আমাদের SingleSetupপ্রথম সংস্করণে বর্ণিত হিসাবে আমাদের মধ্যে একটি খুব অনুরূপ ব্যবস্থা রয়েছে। একটি উদাহরণ হবে

public TestProperties : SingleSetup
{
  public int UserID {get;set;}

  public override DoSetup(ISession session)
  {
    var user = new User("Joe", "Bloggs");
    session.Save(user);
    this.UserID = user.UserID;
  }

  [Test]
  public void TestLastname()
  {
     var user = LoadMyUser(this.UserID); // load the entity
     Assert.AreEqual("Bloggs", user.Lastname);
  }

  [Test]
  public void TestFirstname()
  {
       var user = LoadMyUser(this.UserID);
       Assert.AreEqual("Joe", user.Firstname);
  }
}

তবে উল্লেখগুলি যেগুলি নিশ্চিত করে যে কেবলমাত্র সঠিক এনটাইটগুলি লোড হয়েছে সেগুলি সেটআপপারস্টেস্ট পদ্ধতির ব্যবহার করতে পারে

public TestProperties : SetupPerTest
{
   [Test]
   public void EnsureCorrectReferenceIsLoaded()
   {
      int friendID = 0;
      this.RunTest(session =>
      {
         var user = CreateUserWithFriend();
         session.Save(user);
         friendID = user.Friends.Single().FriendID;
      } () =>
      {
         var user = GetUser();
         Assert.AreEqual(friendID, user.Friends.Single().FriendID);
      });
   }
   [Test]
   public void EnsureOnlyCorrectFriendsAreLoaded()
   {
      int userID = 0;
      this.RunTest(session =>
      {
         var user = CreateUserWithFriends(2);
         var user2 = CreateUserWithFriends(5);
         session.Save(user);
         session.Save(user2);
         userID = user.UserID;
      } () =>
      {
         var user = GetUser(userID);
         Assert.AreEqual(2, user.Friends.Count());
      });
   }
}

সংক্ষেপে উভয় পন্থা আপনি যা পরীক্ষা করার চেষ্টা করছেন তার উপর নির্ভর করে কাজ করে।


2
ইন্টিগ্রেশন পরীক্ষার জন্য এখানে একটি পৃথক পদ্ধতি রয়েছে approach টিএল; ডিআর - পরীক্ষার ডেটা সেটআপ করতে নিজেই অ্যাপ্লিকেশনটি ব্যবহার করুন, পরীক্ষায় প্রতি লেনদেনের রোলব্যাক করুন।
জার্ট আর্নল্ড

3
@ লিয়াথ, দুর্দান্ত সাড়া আপনি EF পরীক্ষার বিষয়ে আমার সন্দেহের বিষয়টি নিশ্চিত করেছেন। আমার প্রশ্ন এটি; আপনার উদাহরণটি খুব কংক্রিটের ক্ষেত্রে, যা ঠিক আছে। তবে আপনি যেমন লক্ষ করেছেন যে আপনার কয়েকশো সত্ত্বা পরীক্ষা করার দরকার হতে পারে। ডিআরওয়াই নীতিটি অনুসরণ করে (নিজেকে পুনরাবৃত্তি করবেন না) প্রতিবার একই বেসিক কোড প্যাটার্নটি পুনরাবৃত্তি না করে আপনি কীভাবে আপনার সমাধানটি স্কেল করবেন?
জেফ্রি এ গোচিন

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

7
আপনার নিজের দ্বারা ইউনিট টেস্টিং ইউনিট পরীক্ষা করা উচিত কিনা সে সম্পর্কে কেউ বেড়াতে নেই on যা ঘটে তা হ'ল আপনাকে এমন কিছু পদ্ধতি পরীক্ষা করতে হবে যা কিছু স্টাফ করে এবং ডাটাবেসে EF কল করার জন্য ঘটে। লক্ষ্যটি হ'ল ইএফকে বিদ্রূপ করা যাতে আপনি আপনার বিল্ড সার্ভারে কোনও ডেটাবেস প্রয়োজন ছাড়াই এই পদ্ধতিটি পরীক্ষা করতে পারেন।
মাফিন ম্যান

4
আমি সত্যিই ভ্রমণ পছন্দ। সময়ের সাথে সাথে সম্পাদনাগুলি যুক্ত করার জন্য ধন্যবাদ - এটি উত্স নিয়ন্ত্রণ পড়া এবং আপনার চিন্তাভাবনা কীভাবে বিকশিত হয়েছে তা বোঝার মতো। আমি কার্যকরী (EF সহ) এবং ইউনিট (উপহাস EF) পার্থক্যকেও সত্যই প্রশংসা করি।
টম লেস

21

এখানে অভিজ্ঞতার প্রতিক্রিয়া

প্রচুর পড়ার পরে আমি আমার পরীক্ষাগুলিতে এফোর্ট ব্যবহার করছি: পরীক্ষার সময় প্রসঙ্গটি এমন একটি কারখানা তৈরি করে যা মেমরির সংস্করণে ফিরে আসে, যা আমাকে প্রতিবার একটি ফাঁকা স্লেটের বিপরীতে পরীক্ষা করতে দেয়। পরীক্ষার বাইরে, কারখানাটি এমন একটিকে সমাধান করা হয় যা পুরো প্রসঙ্গে ফিরে আসে।

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

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

সুতরাং আমি প্রচেষ্টা আকর্ষণীয় মনে করি; আপনার যদি গ্রাউন্ডে দৌড়ানোর দরকার পড়ে তবে দ্রুত শুরু করার এবং ফলাফল পেতে এটি একটি ভাল সরঞ্জাম। তবে আমি মনে করি যে আরও কিছু মার্জিত এবং বিমূর্ত কিছু পরবর্তী পদক্ষেপ হওয়া উচিত এবং এটিই আমি পরবর্তী তদন্ত করতে যাচ্ছি। এই পোস্টটি এটি কোথায় যায় তা দেখতে পছন্দসই :)

যুক্ত করার জন্য সম্পাদনা করুন : চেষ্টাটি উষ্ণ হতে কিছুটা সময় নেয়, সুতরাং আপনি প্রায় দেখছেন। পরীক্ষা শুরুতে 5 সেকেন্ড আপনার পরীক্ষার স্যুট খুব দক্ষ হওয়ার প্রয়োজন হলে এটি আপনার পক্ষে সমস্যা হতে পারে।


স্পষ্টতার জন্য সম্পাদিত:

আমি ওয়েব সার্ভিস অ্যাপ্লিকেশন পরীক্ষার জন্য প্রচেষ্টা ব্যবহার করেছি। এম প্রবেশ করে এমন প্রতিটি বার্তা IHandlerOf<M>উইন্ডসর হয়ে একটি রাউটে যায় । Castle.Windsor এর সমাধান করে IHandlerOf<M>যা উপাদানটির নির্ভরতা পুনরায় প্রেরণ করে। এই নির্ভরতাগুলির মধ্যে একটি হ'ল DataContextFactoryহ্যান্ডলারকে কারখানার জন্য জিজ্ঞাসা করতে দেয়

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

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


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

2
কেবল যদি এফোর্ট লেনদেনগুলি সঠিকভাবে সমর্থন করে
সেদাত কাপানোগলু

CSV লোডার সহ স্ট্রিংগুলির জন্য প্রয়াসের একটি বাগ রয়েছে, যখন আমরা স্ট্রিংগুলিতে নাল পরিবর্তে '' ব্যবহার করি।
স্যাম

13

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

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

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


ধন্যবাদ @ জাস্টিন আমি রেপোজিটরি প্যাটার্ন সম্পর্কে জানি, তবে ayende.com/blog/4784/… এবং লস্টেচিজস / জিমিবোগার্ড / ২০০৯ / ০৯ / ১১ / অন্যত্রের মধ্যে- রিপোজিটরির মতো জিনিসগুলি পড়ার ফলে আমি ভাবতে পারি যে আমি ডন করি না এই বিমূর্ত স্তরটি চাই না, তবে তারপরে আবার এগুলি কোয়েরি পদ্ধতির বিষয়ে আরও কথা বলে যা খুব বিভ্রান্ত হয়।
মোডিকা

7
@ মোডিকা আয়েন্দে সমালোচনার জন্য সংগ্রহস্থলের প্যাটার্নটির একটি খারাপ প্রয়োগ বেছে নিয়েছেন এবং ফলস্বরূপ 100% সঠিক - এটির ইঞ্জিনিয়ারড এবং কোনও সুবিধা দেয় না। একটি ভাল বাস্তবায়ন ডাল বাস্তবায়ন থেকে আপনার কোডের একক-পরীক্ষামূলক অংশগুলি পৃথক করে। এনএইচবারনেট এবং ইএফ ব্যবহার করে কোডকে ইউনিট পরীক্ষায় সরাসরি (অসম্ভব না হলে) কঠিন করে তোলে এবং কঠোর একঘেয়েমি কোডবেস বাড়ে। আমি এখনও সংগ্রহশালার প্যাটার্ন সম্পর্কে কিছুটা সংশয়ী, তবে আমি 100% নিশ্চিত যে আপনার ডাল প্রয়োগ একরকমভাবে বিচ্ছিন্ন করা দরকার এবং আমি এখন অবধি খুঁজে পাওয়া ভাল জিনিসটি হ'ল সংগ্রহস্থল।
জাস্টিন

2
@ মোডিকা আবার দ্বিতীয় নিবন্ধটি পড়ুন। "আমি এই বিমূর্ত স্তরটি চাই না" তিনি যা বলেন তা নয়। প্লাস, ফাউলারের ( মার্টিনফোওয়াল.ইইএ গুগলালগ / রিপোসিটরি এইচটিএমএল ) বা ডিডিডি ( ডিডিডিকমিনিউশন.আর.সোর্সেস / ডিডিডি_টারমস ) থেকে মূল সংগ্রহস্থল প্যাটার্ন সম্পর্কে পড়ুন । আসল ধারণাটি পুরোপুরি না বুঝে নায়েসারদের বিশ্বাস করবেন না। তারা যা সত্যই সমালোচনা করে তা হ'ল প্যাটার্নটির সাম্প্রতিক অপব্যবহার, প্যাটার্নটি নিজেই নয় (যদিও তারা সম্ভবত এটি জানেন না)।
guillaume31

1
@ গিল্লুম ৩১ আমি সংগ্রহস্থলের প্যাটার্নের বিপক্ষে নই (আমি এটি বুঝতে পারি) আমি কেবলমাত্র সেই স্তরে ইতিমধ্যে যে বিমূর্ততা রয়েছে তা বিমূর্ত করার প্রয়োজন কিনা তা জানার চেষ্টা করছি এবং যদি আমি এটি বাদ দিতে পারি এবং উপহাসের মাধ্যমে সরাসরি EF এর বিরুদ্ধে পরীক্ষা করতে পারি এবং এটি আমার প্রয়োগগুলিতে উচ্চতর স্তর পর্যন্ত আমার পরীক্ষাগুলিতে এটি ব্যবহার করুন। অতিরিক্ত, আমি যদি রেপো ব্যবহার না করি তবে আমি রেফার সাহায্যে EF বর্ধিত বৈশিষ্ট্য সেটটির সুবিধা পাব।
মোডিকা

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

9

সুতরাং এখানে জিনিসটি রয়েছে, সত্তা ফ্রেমওয়ার্ক এটি বাস্তবায়ন যা এটি ডাটাবেস ইন্টারঅ্যাকশনটির জটিলতার বিমূর্ততা সত্ত্বেও, সরাসরি ইন্টারঅ্যাক্ট করা এখনও শক্ত সংযোগ এবং এই কারণেই এটি পরীক্ষা করতে বিভ্রান্তিকর।

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

এই কথাটি সহ, এবং EF বাস্তবায়ন হ'ল সত্যটি গ্রহণ করে আমি সম্ভবত কোনও সংগ্রহস্থল বিমূর্ত করার ধারণাটিকে সমর্থন করব। কিছুটা বাড়াবাড়ি লাগছে? এটি নয়, কারণ আপনি এমন কোনও সমস্যা সমাধান করছেন যা ডেটা বাস্তবায়ন থেকে আপনার কোডকে বিচ্ছিন্ন করে দিচ্ছে।

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

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

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


8

আমি পরীক্ষার কোডটি ইউনিট করব না যার মালিক নেই। আপনি এখানে কী পরীক্ষা করছেন, যে এমএসএফটি সংকলক কাজ করে?

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

//this is testable just inject a mock of IProductDAO during unit testing
public class ProductService : IProductService
{
    private IProductDAO _productDAO;

    public ProductService(IProductDAO productDAO)
    {
        _productDAO = productDAO;
    }

    public List<Product> GetAllProducts()
    {
        return _productDAO.GetAll();
    }

    ...
}

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


1
উত্তরের জন্য ধন্যবাদ, তবে আপনি যেখানে এই স্তরের পিছনে EF এর অভ্যন্তরীন গোপন রাখছেন এমন একটি সংগ্রহস্থল বলতে এর পার্থক্য কী হবে? আমি সত্যিই বিমূর্ত EF করতে চাই না, যদিও আমি এখনও আইকনটেক্সট ইন্টারফেসের সাথে এটি করতে পারি? আমি
এটিতে

3
@ মোডিকা এ রেপোও ঠিক আছে। যে প্যাটার্ন আপনি চান। "আমি সত্যিই বিমূর্ত EF করতে চাই না" আপনি কি পরীক্ষার যোগ্য কোড চান নাকি?
জোনাথন হেনসন

1
@ মোডিকা আমার বক্তব্য আপনি যদি আপনার উদ্বেগ আলাদা না করেন তবে আপনার কাছে কোনও পরীক্ষণযোগ্য কোড থাকবে না। ডেটা অ্যাক্সেস এবং বিজনেস লজিক ভাল রক্ষণাবেক্ষণযোগ্য পরীক্ষা বন্ধ করতে পৃথক স্তরে থাকতে হবে।
জোনাথন হেনসন

2
আমি কেবল কোনও রেপোজিটরি অ্যাবস্ট্রাকশনে ইএফকে গুটিয়ে ফেলা জরুরী মনে করি নি যেহেতু মূলত আইডিবিসেটগুলি রেপো এবং প্রসঙ্গটি UOW হয়, আমি আমার প্রশ্নটি কিছুটা আপডেট করব যা বিভ্রান্তিকর হতে পারে। সমস্যাটি কোনও বিমূর্ততার সাথে আসে এবং মূল বিষয়টি হ'ল আমি যা পরীক্ষা করছি ঠিক সে কারণেই আমার কুইরিগুলি একই সীমানায় চলবে না (লিনাক-টু-সত্তা বনাম লিনক-টু-অবজেক্টস) তাই যদি আমি কেবল পরীক্ষা করে দেখি যে আমার পরিষেবাটি একটি করে তোলে কলটি যে কিছুটা অপব্যয়যুক্ত বলে মনে হচ্ছে বা আমি এখানে ভাল আছি?
মোডিকা

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

8

আমি এই বিবেচনায় পৌঁছানোর জন্য কিছুটা সময় চঞ্চল হয়ে পড়েছি:

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

2- সংগ্রহস্থল প্যাটার্নটি কিছুটা কঠোর এবং সময় সাপেক্ষ।

সুতরাং আমি এই পদ্ধতির সাথে উঠে এসেছি, যা আমি সেরা হিসাবে মনে করি না, তবে আমার প্রত্যাশা পূরণ করেছি:

Use TransactionScope in the tests methods to avoid changes in the database.

এটি করার জন্য এটি প্রয়োজনীয়:

1- টেস্ট প্রকল্পে সত্ত্বা ফ্রেমওয়ার্ক ইনস্টল করুন। 2- পরীক্ষা প্রকল্পের app.config ফাইলে সংযোগের স্ট্রিং রাখুন। 3- dll সিস্টেম রেফারেন্স। টেস্ট প্রকল্পে লেনদেন।

অনন্য পার্শ্ব প্রতিক্রিয়া হ'ল লেনদেনটি বাতিল হওয়া সত্ত্বেও identityোকানোর চেষ্টা করার সময় পরিচয় বীজ বৃদ্ধি পাবে। তবে যেহেতু পরীক্ষাগুলি কোনও ডেভলপমেন্ট ডাটাবেসের বিরুদ্ধে করা হয়, তাই এটি কোনও সমস্যা হওয়া উচিত নয়।

কোডের উদাহরণ:

[TestClass]
public class NameValueTest
{
    [TestMethod]
    public void Edit()
    {
        NameValueController controller = new NameValueController();

        using(var ts = new TransactionScope()) {
            Assert.IsNotNull(controller.Edit(new Models.NameValue()
            {
                NameValueId = 1,
                name1 = "1",
                name2 = "2",
                name3 = "3",
                name4 = "4"
            }));

            //no complete, automatically abort
            //ts.Complete();
        }
    }

    [TestMethod]
    public void Create()
    {
        NameValueController controller = new NameValueController();

        using (var ts = new TransactionScope())
        {
            Assert.IsNotNull(controller.Create(new Models.NameValue()
            {
                name1 = "1",
                name2 = "2",
                name3 = "3",
                name4 = "4"
            }));

            //no complete, automatically abort
            //ts.Complete();
        }
    }
}

1
আসলে, আমি এই সমাধানটি অনেক পছন্দ করি। বাস্তবায়নের জন্য দুর্দান্ত সহজ এবং আরও বাস্তব পরীক্ষামূলক দৃশ্যাবলী। ধন্যবাদ!
opালুপা

1
EF 6 এর সাহায্যে আপনি DbContext.Database.BeginTransaction ব্যবহার করবেন, তাই না?
সুইস কোডার

5

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


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

3

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

প্রথমত, আমি ইএফ কোর থেকে ইন-মেমরি সরবরাহকারীটি ব্যবহার করতে পছন্দ করব তবে এটি এএফ about এর সম্পর্কে Furthermore এছাড়াও, রেভেনডিবি-র মতো অন্যান্য স্টোরেজ সিস্টেমের জন্য আমি ইন-মেমরি ডাটাবেস সরবরাহকারীর মাধ্যমেও পরীক্ষার প্রবক্তা হব। আবার - এটি বিশেষভাবে অনেক অনুষ্ঠান ছাড়াই ইএফ-ভিত্তিক কোড পরীক্ষা করতে সহায়তা করে ।

একটি নিদর্শন নিয়ে আসার সময় আমার লক্ষ্যগুলি এখানে ছিল:

  • দলের অন্য বিকাশকারীদের বুঝতে এটি অবশ্যই সহজ must
  • এটি অবশ্যই বেস্ট সম্ভাব্য স্তরে EF কোডটি বিচ্ছিন্ন করতে হবে
  • এটি অবশ্যই অদ্ভুত বহু-দায়বদ্ধ ইন্টারফেস (যেমন একটি "জেনেরিক" বা "সাধারণ" সংগ্রহস্থল নিদর্শন) তৈরি করা জড়িত না
  • এটি অবশ্যই ইউনিট পরীক্ষায় কনফিগার করতে এবং সেটআপ করা সহজ

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

আমি যেভাবে এটি অর্জন করেছি তা হল সহজভাবে ডেডিকেটেড ক্যোয়ারী এবং কমান্ড ক্লাসগুলিতে ইএফ কোড এনপ্যাপুলেশন করার মাধ্যমে । ধারণাটি সহজ: কেবল কোনও ক্লাসে যে কোনও ইএফ কোডটি लपेटুন এবং ক্লাসগুলির একটি ইন্টারফেসের উপর নির্ভর করুন যা এটি মূলত ব্যবহার করবে। আমার যে মুখ্য সমস্যাটি সমাধান করা দরকার তা হ'ল ক্লাসে অসংখ্য নির্ভরতা যুক্ত করা এবং আমার পরীক্ষাগুলিতে প্রচুর কোড স্থাপন করা।

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

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

প্রথমে বলি যে আমাদের এমন একটি পরিষেবা রয়েছে যাতে ব্যবসায়িক যুক্তি রয়েছে যা আমাদের পরীক্ষা করতে হবে:

public class FeatureService {

  private readonly IMediator _mediator;

  public FeatureService(IMediator mediator) {
    _mediator = mediator;
  }

  public async Task ComplexBusinessLogic() {
    // retrieve relevant objects

    var results = await _mediator.Send(new GetRelevantDbObjectsQuery());
    // normally, this would have looked like...
    // var results = _myDbContext.DbObjects.Where(x => foo).ToList();

    // perform business logic
    // ...    
  }
}

আপনি কি এই পদ্ধতির সুবিধা দেখতে শুরু করেন? আপনি কেবল বর্ণনামূলক ক্লাসে সমস্ত EF- সম্পর্কিত কোডকে স্পষ্টভাবে আবদ্ধ করছেন না, আপনি "কীভাবে" এই অনুরোধটি পরিচালনা করা হয় তার বাস্তবায়ন উদ্বেগকে সরিয়ে দিয়ে এক্সটেনসিবিলিটিটি মঞ্জুর করছেন - প্রাসঙ্গিক বিষয়গুলি EF, মঙ্গোডিবি থেকে আসে কিনা এই শ্রেণীর যত্ন নেই doesn't বা একটি পাঠ্য ফাইল।

এখন মিডিয়াটিআর এর মাধ্যমে অনুরোধ এবং হ্যান্ডলারের জন্য:

public class GetRelevantDbObjectsQuery : IRequest<DbObject[]> {
  // no input needed for this particular request,
  // but you would simply add plain properties here if needed
}

public class GetRelevantDbObjectsEFQueryHandler : IRequestHandler<GetRelevantDbObjectsQuery, DbObject[]> {
  private readonly IDbContext _db;

  public GetRelevantDbObjectsEFQueryHandler(IDbContext db) {
    _db = db;
  }

  public DbObject[] Handle(GetRelevantDbObjectsQuery message) {
    return _db.DbObjects.Where(foo => bar).ToList();
  }
}

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

তাহলে আমাদের বৈশিষ্ট্য পরিষেবাটির ইউনিট পরীক্ষাটি দেখতে কেমন? এটা সহজ উপায়। এই ক্ষেত্রে, আমি উপহাস করার জন্য Moq ব্যবহার করছি (যা আপনাকে খুশি করে তা ব্যবহার করুন):

[TestClass]
public class FeatureServiceTests {

  // mock of Mediator to handle request/responses
  private Mock<IMediator> _mediator;

  // subject under test
  private FeatureService _sut;

  [TestInitialize]
  public void Setup() {

    // set up Mediator mock
    _mediator = new Mock<IMediator>(MockBehavior.Strict);

    // inject mock as dependency
    _sut = new FeatureService(_mediator.Object);
  }

  [TestCleanup]
  public void Teardown() {

    // ensure we have called or expected all calls to Mediator
    _mediator.VerifyAll();
  }

  [TestMethod]
  public void ComplexBusinessLogic_Does_What_I_Expect() {
    var dbObjects = new List<DbObject>() {
      // set up any test objects
      new DbObject() { }
    };

    // arrange

    // setup Mediator to return our fake objects when it receives a message to perform our query
    // in practice, I find it better to create an extension method that encapsulates this setup here
    _mediator.Setup(x => x.Send(It.IsAny<GetRelevantDbObjectsQuery>(), default(CancellationToken)).ReturnsAsync(dbObjects.ToArray()).Callback(
    (GetRelevantDbObjectsQuery message, CancellationToken token) => {
       // using Moq Callback functionality, you can make assertions
       // on expected request being passed in
       Assert.IsNotNull(message);
    });

    // act
    _sut.ComplexBusinessLogic();

    // assertions
  }

}

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

আপনি যদি ভাবছেন যে আমি কীভাবে এই ক্লাসগুলি সংগঠিত করি তবে এটি বেশ সহজ:

- MyProject
  - Features
    - MyFeature
      - Queries
      - Commands
      - Services
      - DependencyConfig.cs (Ninject feature modules)

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

এটি আমার সমস্ত মাপদণ্ড পূরণ করে: এটি স্বল্প-অনুষ্ঠান, এটি বোঝা সহজ এবং অতিরিক্ত গোপন সুবিধা রয়েছে। উদাহরণস্বরূপ, আপনি কীভাবে সংরক্ষণ পরিবর্তনগুলি পরিচালনা করেন? এখন আপনি কোনও রোল ইন্টারফেস ব্যবহার করে আপনার ডিবি প্রসঙ্গটি সহজ করতে পারেন (IUnitOfWork.SaveChangesAsync()) এবং একক ভূমিকা ইন্টারফেসে মক কলগুলি বা আপনি আপনার অনুরোধহ্যান্ডলারগুলির মধ্যে প্রতিশ্রুতিবদ্ধ / ঘূর্ণায়মান আবদ্ধ করতে পারেন - তবে আপনি যতক্ষণ এটি রক্ষণাবেক্ষণযোগ্য ততক্ষণ আপনি এটি করতে পছন্দ করেন। উদাহরণস্বরূপ, আমি একটি একক জেনেরিক অনুরোধ / হ্যান্ডলার তৈরি করতে প্ররোচিত হয়েছিল যেখানে আপনি কেবল একটি ইএফ বস্তুটি পাস করেছেন এবং এটি সংরক্ষণ / আপডেট / মুছে ফেলবে - তবে আপনাকে আপনার উদ্দেশ্য কী তা জিজ্ঞাসা করতে হবে এবং মনে রাখতে হবে যে আপনি যদি চান অন্য স্টোরেজ সরবরাহকারী / প্রয়োগের সাথে হ্যান্ডলারটি সরিয়ে আনা, আপনার সম্ভবত সম্ভবত স্পষ্ট নির্দেশাবলী / কোয়েরি তৈরি করা উচিত যা আপনি যা করতে চান তা প্রতিনিধিত্ব করে। প্রায়শই না, একক পরিষেবা বা বৈশিষ্ট্যের জন্য নির্দিষ্ট কিছু প্রয়োজন হবে - জেনেরিক স্টাফের প্রয়োজন হওয়ার আগে তৈরি করবেন না।

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

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


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

3

প্রচেষ্টা রয়েছে যা মেমরি সত্তা ফ্রেমওয়ার্ক ডাটাবেস সরবরাহকারী। আমি আসলে এটি চেষ্টা করে দেখিনি ... হা এই প্রশ্নের মধ্যে উল্লেখ করা হয়েছিল কেবল স্পষ্ট!

বিকল্পভাবে আপনি এন্টি ফ্রেমওয়ার্ককরে স্যুইচ করতে পারেন যা অন্তর্নির্মিত মেমরি ডেটাবেস সরবরাহকারী রয়েছে।

https://blog.goyello.com/2016/07/14/save-time-mocking-use-your-real-entity-framework-dbcontext-in-unit-tests/

https://github.com/tamasflamich/effort

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

return new MyContext(@"Server=(localdb)\mssqllocaldb;Database=EFProviders.InMemory;Trusted_Connection=True;");

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

আপনার কাছে উপহাস করার মতো প্রসঙ্গ থাকলে এই মোইক সহায়ক ( কোডেপ্রজেক্ট / টিপস 104545590/… ) কাজ করে। যদি আপনার মেক-আউট প্রসঙ্গটি কোনও তালিকার সাহায্যে সমর্থন করে তবে এটি কোনও এসকেএল ডাটাবেস দ্বারা সমর্থিত প্রসঙ্গের মতো আচরণ করবে না।
অ্যান্ড্রু পেট

2

আমি কোডের অন্যান্য অংশগুলি থেকে আমার ফিল্টারগুলি পৃথক করতে চাই এবং আমার ব্লগটিতে আমি এখানে যেমন রূপরেখি হিসাবেছি সেগুলি পরীক্ষা করতে চাই http://coding.grax.com/2013/08/testing-custom-linq-filter-operators.html

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


0

আপনি সত্তা কাঠামোটি কী করবেন (যা আপনার প্রত্যাশাগুলি যাচাই করবে) তা প্রত্যাশা করে যাচাই করা গুরুত্বপূর্ণ। এটি করার একটি উপায় যা আমি সফলতার সাথে ব্যবহার করেছি, তা এই উদাহরণে প্রদর্শিত মোখ ব্যবহার করা হচ্ছে (এই উত্তরটি অনুলিপি করার জন্য):

https://docs.microsoft.com/en-us/ef/ef6/fundamentals/testing/mocking

তবে সাবধান হন ... একটি এসকিউএল প্রসঙ্গে আপনার লিনকের ক্যোয়ারিতে উপযুক্ত "অর্ডারবাই" না থাকলে নির্দিষ্ট অর্থে জিনিসগুলি ফিরিয়ে দেওয়ার গ্যারান্টি দেওয়া হয় না, সুতরাং যখন আপনি কোনও স্মৃতিশক্তি তালিকা ব্যবহার করে পরীক্ষা করেন তখন পাস হওয়া জিনিসগুলি লেখার সম্ভাবনা থাকে ( লিনক-টু-সত্তা) তবে (লিনক-টু-এসকিএল) ব্যবহৃত হয়ে গেলে আপনার ইউট / লাইভ পরিবেশে ব্যর্থ।

আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.