গোতে ইউনিট পরীক্ষা এবং ইন্টিগ্রেশন পরীক্ষার পৃথককরণ


102

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

সর্বাধিক সোজা-ফরোয়ার্ড কৌশলটি মনে হচ্ছে মূলত একটি অন্তর্ভুক্ত পতাকাটিকে সংজ্ঞায়িত করা হবে:

var runIntegrationTests = flag.Bool("integration", false
    , "Run the integration tests (in addition to the unit tests)")

এবং তারপরে প্রতিটি ইন্টিগ্রেশন পরীক্ষার শীর্ষে একটি if-বিবৃতি যুক্ত করতে:

if !*runIntegrationTests {
    this.T().Skip("To run this test, use: go test -integration")
}

এটি কি আমি করতে পারি সেরা? আমি সম্ভবত নামকরণের কনভেনশন বা আমার পক্ষে এটি সম্পাদন করে এমন কিছু আছে কিনা তা দেখার জন্য সাক্ষ্যদানকারী ডকুমেন্টেশনের সন্ধান করেছি, কিন্তু কিছুই পাইনি। আমি কিছু অনুপস্থিত করছি?


4
আমি মনে করি stdlib পরীক্ষাটি অক্ষম করতে শর্ট ব্যবহার করে যা নেটওয়ার্কে আঘাত করে (এবং অন্যান্য দীর্ঘমেয়াদি স্টাফগুলিও)। অন্যভাবে আপনার সমাধান ঠিক আছে বলে মনে হচ্ছে।
ভোলকার

- শর্ট একটি ভাল বিকল্প, যেমন আপনার কাস্টম বিল্ড পতাকাগুলি, তবে আপনার পতাকাগুলি প্রধান হওয়া উচিত নয়। আপনি যদি var integration = flag.Bool("integration", true, "Enable integration testing.")কোনও ফাংশনের বাইরের হিসাবে
ভেরিটটি

উত্তর:


161

@ আইনার-জি পৃথক পরীক্ষার জন্য বেশ কয়েকটি দুর্দান্ত নিদর্শনগুলির পরামর্শ দেয়।

সাউন্ডক্লাউড থেকে গো অনুশীলনের এই সেট কোন পরীক্ষাগুলি চালাতে হবে তা বেছে নিতে বিল্ড ট্যাগগুলি ( বিল্ড প্যাকেজটির "বিল্ড সীমাবদ্ধতা" বিভাগে বর্ণিত ) ব্যবহার করার পরামর্শ দেয়:

একটি ইন্টিগ্রেশন_েস্ট.গো লিখুন এবং এটিকে ইন্টিগ্রেশনের বিল্ড ট্যাগ দিন। পরিষেবার ঠিকানা এবং সংযুক্ত স্ট্রিংগুলির মতো জিনিসের জন্য (গ্লোবাল) পতাকাগুলি সংজ্ঞায়িত করুন এবং এগুলি আপনার পরীক্ষায় ব্যবহার করুন।

// +build integration

var fooAddr = flag.String(...)

func TestToo(t *testing.T) {
    f, err := foo.Connect(*fooAddr)
    // ...
}

গো পরীক্ষাটি বিল্ড ট্যাগগুলি ঠিক যেমন বিল্ড করতে যান, তাই আপনি কল করতে পারেন go test -tags=integration । এটি একটি প্যাকেজ প্রধানকে সংশ্লেষিত করে যা পতাকাটি বলে। পার্স, সুতরাং ঘোষিত ও দৃশ্যমান যে কোনও পতাকা প্রসেস হবে এবং আপনার পরীক্ষাগুলিতে উপলভ্য হবে।

অনুরূপ বিকল্প হিসাবে, আপনার বিল্ড শর্তটি ব্যবহার করে ডিফল্টরূপে চালিত ইন্টিগ্রেশন টেস্টগুলিও থাকতে পারে // +build !unit , এবং তারপরে চালনার মাধ্যমে চাহিদা অনুসারে অক্ষম করুন go test -tags=unit

@ অ্যাডাম্যাক মন্তব্য:

অন্য কারও জন্য বিল্ড ট্যাগগুলি ব্যবহার করার চেষ্টা করার জন্য, // +build testমন্তব্যটি আপনার ফাইলের প্রথম লাইন, এবং মন্তব্যটির পরে আপনি একটি ফাঁকা লাইন অন্তর্ভুক্ত করবেন এটি গুরুত্বপূর্ণ, অন্যথায় -tagsকমান্ড নির্দেশটিকে অগ্রাহ্য করবে।

এছাড়াও, বিল্ড মন্তব্যে ব্যবহৃত ট্যাগটিতে ড্যাশ থাকতে পারে না, যদিও আন্ডারস্কোরগুলি অনুমোদিত। উদাহরণস্বরূপ, // +build unit-testsকাজ করবে না, যেখানে // +build unit_testsহবে।


4
আমি এটি কিছু সময়ের জন্য ব্যবহার করে আসছি এবং এটি এখন পর্যন্ত সবচেয়ে যুক্তিযুক্ত এবং সহজ পদ্ধতির।
ওরি ব্যান্ড

4
যদি আপনার একই প্যাকেজে ইউনিট পরীক্ষা থাকে তবে আপনাকে ইউনিট পরীক্ষা করতে হবে // + build unitএবং পরীক্ষা চালানোর জন্য -ট্যাগ ইউনিট ব্যবহার করতে হবে
লিওসিবিএস

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

4
অন্য কারও জন্য বিল্ড ট্যাগগুলি ব্যবহার করার চেষ্টা করার জন্য, // +buildটেস্ট মন্তব্যটি আপনার ফাইলের প্রথম লাইন, এবং আপনি মন্তব্যের পরে একটি ফাঁকা লাইন অন্তর্ভুক্ত করবেন, অন্যথায় -tagsকমান্ড নির্দেশটিকে অগ্রাহ্য করবে। এছাড়াও, বিল্ড মন্তব্যে ব্যবহৃত ট্যাগটিতে ড্যাশ থাকতে পারে না, যদিও আন্ডারস্কোরগুলি অনুমোদিত। উদাহরণস্বরূপ, // +build unit-testsহবে কাজ না, যেহেতু // +build unit_testsইচ্ছা
adamc

6
কিভাবে ওয়াইল্ডকার্ড পরিচালনা করবেন? go test -tags=integration ./...কাজ করে না, ট্যাগটিকে উপেক্ষা করে
এরিকা ডসোজা

57

আমার মন্তব্যে সম্প্রসারিত করার @ Ainar-জি এর চমৎকার উত্তর, বিগত বছরে আমি সমন্বয় ব্যবহার করছেন -shortসঙ্গেIntegration কনভেনশন নামকরণ উভয় বোথ ওয়ার্ল্ডস শ্রেষ্ঠ অর্জন করা।

ইউনিট এবং ইন্টিগ্রেশন একই ফাইলের সাথে সম্প্রীতি পরীক্ষা করে

পতাকা তৈরির আগে আমাকে একাধিক ফাইল রাখতে বাধ্য করেছিল ( services_test.go,services_integration_test.go ইত্যাদি)।

পরিবর্তে, নীচে এই উদাহরণটি নিন যেখানে প্রথম দুটি ইউনিট পরীক্ষা এবং শেষে আমার একটি ইন্টিগ্রেশন পরীক্ষা রয়েছে:

package services

import "testing"

func TestServiceFunc(t *testing.T) {
    t.Parallel()
    ...
}

func TestInvalidServiceFunc3(t *testing.T) {
    t.Parallel()
    ...
}

func TestPostgresVersionIntegration(t *testing.T) {
    if testing.Short() {
        t.Skip("skipping integration test")
    }
    ...
}

লক্ষ করুন শেষ পরীক্ষায় কনভেনশন রয়েছে:

  1. ব্যবহার Integrationপরীক্ষার নাম ।
  2. -shortপতাকা নির্দেশের অধীনে চলছে কিনা তা পরীক্ষা করা হচ্ছে ।

মূলত, অনুমানটি যায়: "সমস্ত পরীক্ষা সাধারণত লিখুন it এটি দীর্ঘমেয়াদী পরীক্ষা বা একটি ইন্টিগ্রেশন টেস্ট হয়, এই নামকরণ কনভেনশনটি অনুসরণ করুন এবং পরীক্ষা করুন -short আপনার সমবয়সীদের কাছে ভাল লাগার করুন।"

কেবল ইউনিট পরীক্ষা চালান:

go test -v -short

এটি আপনাকে বার্তাগুলির একটি দুর্দান্ত সেট সরবরাহ করে:

=== RUN   TestPostgresVersionIntegration
--- SKIP: TestPostgresVersionIntegration (0.00s)
        service_test.go:138: skipping integration test

শুধুমাত্র ইন্টিগ্রেশন টেস্টগুলি চালান:

go test -run Integration

এটি কেবল সংহতকরণ পরীক্ষা চালায়। উত্পাদনে ধোঁয়া পরীক্ষার ক্যানারিগুলির জন্য দরকারী।

স্পষ্টতই এই পদ্ধতির নেতিবাচক দিকটি হ'ল যদি কেউ চালায় go test, -shortপতাকা ব্যতীত, এটি সমস্ত পরীক্ষা - ইউনিট এবং ইন্টিগ্রেশন পরীক্ষা চালানোর জন্য ডিফল্ট হবে।

বাস্তবে, যদি আপনার প্রকল্পটি ইউনিট এবং ইন্টিগ্রেশন পরীক্ষার জন্য যথেষ্ট পরিমাণে বড় হয়, তবে আপনি সম্ভবত এটি ব্যবহার Makefileকরার জন্য আপনার সাধারণ নির্দেশিকা থাকতে পারে এমন জায়গা ব্যবহার go test -shortকরছেন। অথবা, কেবল এটি আপনার README.mdফাইলে রেখে দিনটি কল করুন।


4
সরলতা পছন্দ
জ্যাকব স্ট্যানলি

আপনি কি প্যাকেজের সর্বজনীন অংশগুলিতে অ্যাক্সেস পেতে এই জাতীয় পরীক্ষার জন্য পৃথক প্যাকেজ তৈরি করেন? নাকি সব মিশ্র?
ডকিল

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

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

হ্যাঁ, এটা ঠিক আমি এটি কীভাবে করি তার একটি পরিষ্কার উদাহরণ এখানে দেওয়া হয়েছে: github.com/eduncan911/podcast (উদাহরণস্বরূপ 100% কোড কভারেজ লক্ষ্য করুন)
eduncan911

51

আমি তিনটি সম্ভাব্য সমাধান দেখতে পাচ্ছি। প্রথমটি ইউনিট পরীক্ষার জন্য শর্ট মোড ব্যবহার করা use সুতরাং আপনি go test -shortইউনিট পরীক্ষা এবং একই ছাড়া ব্যবহার করবে-short পতাকাটি আপনার ইন্টিগ্রেশন পরীক্ষা চালানোর জন্য। স্ট্যান্ডার্ড লাইব্রেরিটি দীর্ঘ-চলমান পরীক্ষাগুলি এড়াতে বা সহজ ডেটা সরবরাহ করে দ্রুত চালিত করতে শর্ট মোড ব্যবহার করে।

দ্বিতীয়টি হ'ল কনভেনশন ব্যবহার করা এবং আপনার পরীক্ষাগুলি কল করা TestUnitFooঅথবা TestIntegrationFooতারপরে কোন পরীক্ষাগুলি চালানো হবে তা বোঝাতে -runটেস্টিং ফ্ল্যাগ ব্যবহার করা । সুতরাং আপনি go test -run 'Unit'ইউনিট পরীক্ষার জন্য ব্যবহার করবেন এবংgo test -run 'Integration' জন্য সংহতকরণ পরীক্ষার জন্য

তৃতীয় বিকল্পটি হ'ল এনভায়রনমেন্ট ভেরিয়েবল ব্যবহার করা এবং এটির মাধ্যমে আপনার পরীক্ষাগুলির সেটআপে আসুন os.Getenv। তারপরে আপনি go testইউনিট পরীক্ষার জন্য সহজ ব্যবহার করবেন এবংFOO_TEST_INTEGRATION=true go test জন্য ইন্টিগ্রেশন পরীক্ষার জন্য ।

-shortসমাধানটি আমি ব্যক্তিগতভাবে পছন্দ করি যেহেতু এটি সহজ এবং স্ট্যান্ডার্ড লাইব্রেরিতে ব্যবহৃত হয়, সুতরাং মনে হচ্ছে এটি দীর্ঘ-চলমান পরীক্ষাগুলি পৃথককরণ / সরলকরণের একটি বাস্তব উপায়। তবে -runএবং os.Getenvসমাধানগুলি আরও নমনীয়তা সরবরাহ করে (আরও সতর্কতাও প্রয়োজন, যেহেতু রেজিেক্সসগুলি এর সাথে জড়িত -run)।


4
নোট করুন যে সম্প্রদায় পরীক্ষা চালকরা (উদাঃ Tester-Go) আইডিইগুলিতে সাধারণ (অ্যাটম, সাবলাইম, ইত্যাদি) এবং অন্যদের সাথে -shortপতাকা সহ চালানোর জন্য অন্তর্নির্মিত বিকল্প -coverageরয়েছে। অতএব, আমি পরীক্ষার নামের সাথে উভয় সংহতকরণের সংমিশ্রণটি ব্যবহার করি if testing.Short()those এটি আমাকে উভয় বিশ্বের সেরা থাকতে দেয়: -shortআইডিইগুলির সাথে চালানো , এবং স্পষ্টভাবে শুধুমাত্র সংহতকরণ পরীক্ষা দিয়ে চালানোgo test -run "Integration"
eduncan911

5

আমি সম্প্রতি এর সমাধান পেতে চেষ্টা করছিলাম। এগুলি আমার মানদণ্ড ছিল:

  • সমাধানটি সর্বজনীন হতে হবে
  • ইন্টিগ্রেশন পরীক্ষার জন্য আলাদা প্যাকেজ নেই
  • বিচ্ছেদটি সম্পূর্ণ হওয়া উচিত (আমার কেবলমাত্র সংহতকরণ পরীক্ষা চালানো উচিত) )
  • ইন্টিগ্রেশন পরীক্ষার জন্য কোনও বিশেষ নামকরণের সম্মেলন নেই
  • অতিরিক্ত সরঞ্জামদান না করে এটি ভালভাবে কাজ করা উচিত

পূর্বোক্ত সমাধানগুলি (কাস্টম ফ্ল্যাগ, কাস্টম বিল্ড ট্যাগ, পরিবেশের ভেরিয়েবল) সত্যিই উপরের সমস্ত মানদণ্ডটি পূরণ করতে পারে নি, তাই কিছুটা খনন এবং খেলার পরে আমি এই সমাধানটি নিয়ে এসেছি:

package main

import (
    "flag"
    "regexp"
    "testing"
)

func TestIntegration(t *testing.T) {
    if m := flag.Lookup("test.run").Value.String(); m == "" || !regexp.MustCompile(m).MatchString(t.Name()) {
        t.Skip("skipping as execution was not requested explicitly using go test -run")
    }

    t.Parallel()

    t.Run("HelloWorld", testHelloWorld)
    t.Run("SayHello", testSayHello)
}

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

ব্যবহার

কোনও প্রকল্পের সমস্ত প্যাকেজ জুড়েই ইন্টিগ্রেশন পরীক্ষা চালান:

go test -v ./... -run ^TestIntegration$

সমস্ত পরীক্ষা চালান ( নিয়মিত এবং সংহতকরণ):

go test -v ./... -run .\*

কেবল নিয়মিত পরীক্ষা চালান :

go test -v ./...

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

পুরো উদাহরণটি এখানে পাওয়া যাবে: https://github.com/sagikazarmark/modern-go-application

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