জুনিট - রান আপ সেটআপ পদ্ধতিটি একবার


119

আমি কয়েকটি পরীক্ষা দিয়ে একটি ক্লাস স্থাপন করেছি এবং ব্যবহারের পরিবর্তে @Beforeআমার কাছে একটি সেটআপ পদ্ধতি থাকা চাই যা সমস্ত পরীক্ষার আগে কেবল একবার কার্যকর হয়। জুনিট 4.8 দিয়ে কি তা সম্ভব?


1
: একটি RunListener এ চেহারা আছে stackoverflow.com/a/14773170/548473
গ্রেগরি Kislin

উত্তর:


205

যদিও আমি @assylias এর সাথে একমত যে ব্যবহারটি @BeforeClassএকটি সর্বোত্তম সমাধান যা সর্বদা সুবিধাজনক নয়। বর্ণিত পদ্ধতিটি @BeforeClassঅবশ্যই অচল থাকতে হবে। এটি কিছু পরীক্ষার জন্য খুব অসুবিধে হয় যার পরীক্ষার ক্ষেত্রে উদাহরণ প্রয়োজন। উদাহরণস্বরূপ বসন্ত ভিত্তিক পরীক্ষাগুলি যা @Autowiredবসন্ত প্রসঙ্গে নির্ধারিত পরিষেবাদিগুলির সাথে কাজ করতে ব্যবহার করে।

setUp()এক্ষেত্রে আমি ব্যক্তিগতভাবে টীকা সহ টীকাযুক্ত নিয়মিত পদ্ধতি ব্যবহার করি @Beforeএবং আমার কাস্টম static(!) booleanপতাকাটি পরিচালনা করি :

private static boolean setUpIsDone = false;
.....
public void setUp() {
    if (setUpIsDone) {
        return;
    }
    // do the setup
    setUpIsDone = true;
}

10
কেন এটি স্থির থাকতে হবে সে সম্পর্কে কেনি কেসনের মন্তব্যে যোগ করা। এটি অবশ্যই স্থিতিশীল হতে পারে কারণ প্রতিটি @ টেস্ট পদ্ধতির জন্য JUnit পরীক্ষা শ্রেণির একটি নতুন উদাহরণ ইনস্ট্যান্ট করে। উদাহরণস্বরূপ পরিবর্তনশীল এটি স্থির না হলে প্রতিটি উদাহরণের জন্য এটির ডিফল্ট মান (মিথ্যা) এ পুনরায় সেট করা হবে। আরও তথ্যের জন্য দেখুন: martinfowler.com/bliki/JunitNewInstance.html
dustin.schultz

2
setUp()পদ্ধতিটি সুপারক্লাসে রয়েছে এমন ক্ষেত্রে বাদে এটি কাজ করে - এটি সমাধানের চেষ্টা করার নীচে একটি উত্তর পোস্ট করেছে ।
স্টিভ চেম্বারস

4
আমি একটি 84k প্রতিনিধি সহ কারও কাছে এটি বলতে দ্বিধা বোধ করি, তবে বিয়ারক্লাস আসলে প্রশ্নের উত্তর দেয় না: প্রতিটি পরীক্ষার ক্লাসের শুরুতে বিয়ারক্লাস চালিত হয়। তবে ওপি এমন একটিকে জিজ্ঞাসা করেছিল যা "সমস্ত পরীক্ষার আগে একবার" চালিত হয়। আপনার প্রস্তাবিত সমাধান এটি করতে পারে তবে আপনার সমস্ত পরীক্ষার ক্লাসগুলি একটি "কমন টেস্ট" শ্রেণি বাড়িয়ে তুলতে হবে ...
মাইকে রডেন্ট

1
@ মিকেরোডেন্ট, আইএমএইচও ওপি তার পরীক্ষার ক্ষেত্রে সমস্ত পরীক্ষা সম্পর্কে জিজ্ঞাসা করেছিলেন, সমস্ত পরীক্ষা সামগ্রিকভাবে হয় না। সুতরাং, আপনার মন্তব্য কম প্রাসঙ্গিক। বিটিডাব্লু, যে কোনও ব্যক্তির সুনাম বেশি থাকলেও কিছু বলার জন্য চিন্তা করবেন না। কমপক্ষে এটি আমি করি :) :) অগাস্ট ২০১২ এ আমি যখন প্রশ্নের উত্তর দিয়েছিলাম তখন আমার খ্যাতি উল্লেখযোগ্যভাবে কম ছিল।
অ্যালেক্সার

আমার ক্ষেত্রে কাজ করে না, সেটআপে আরম্ভ করা ভেরিয়েবলগুলি প্রতিটি পরীক্ষার পরে পুনরায় সেট করা হয়, সুতরাং কেবল একবার দীক্ষা করা অর্থহীন।
আফাক্স

89

আপনি ব্যবহার করতে পারেন টীকা :BeforeClass

@BeforeClass
public static void setUpClass() {
    //executed only once, before the first test
}

12
আমি এটি ব্যবহার করতে পারি না, আমার কয়েকটি কয়েকটি সেটআপ পদ্ধতি রয়েছে যা গেটক্লাস ()
Bober02

1
@ বোবার02 এর পূর্বেক্লাসটি সত্যই স্থির হওয়া দরকার। আপনি যদি এটি ব্যবহার করতে না পারেন, অন্য উত্তরটি একটি বিপরীতে সরবরাহ করে।
Assylias

2
নিশ্চিত যে আপনি TheClassYouWant.classনিজের getClass () কলের পরিবর্তে ব্যবহার করতে পারবেন না ? প্রকৃত জাভা হল: String.class.getName()
স্টলসভিক


1
@ মাইক্রোডেন্ট আমি প্রশ্নটি "ক্লাসের সমস্ত পরীক্ষা" হিসাবে বুঝতে পেরেছিলাম - তবে আপনি ঠিক বলেছেন যে ওপি যা চেয়েছিল তা নাও হতে পারে।
assylias

29

5 ইউনাইট এখন একটি পূর্ববর্তী সমস্ত টিকা আছে:

উল্লেখ করে যে বর্তমান ক্লাস বা শ্রেণি শ্রেণিবিন্যাসের সমস্ত @ টেস্ট পদ্ধতির আগে টিক চিহ্ন দেওয়া পদ্ধতিটি কার্যকর করা উচিত; JUnit 4 এর @BeforeClass এর সাথে সাদৃশ্য। এই জাতীয় পদ্ধতি অবশ্যই অচল থাকতে হবে।

5 ইউনাইটের লাইফসাইकल টিকাগুলি শেষ পর্যন্ত এটি ঠিকই পেয়েছে বলে মনে হচ্ছে! আপনি অনুমান করতে পারেন যে কোন টিকাটি এমনকি সন্ধান ছাড়াই উপলব্ধ eg (উদাহরণস্বরূপ @BeEEEach @ আফটারএল)


6
এটি একই সমস্যা ছিল @BeforeClass, এটি করা প্রয়োজন static। আইএমও @ অ্যালেক্সআরের সমাধানটি ভাল।
জেনগার

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

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

এটি কি মাভেনের সাথে কাজ করে যেখানে একাধিক মডিউল রয়েছে তাদের প্রতিটি পরীক্ষা দিয়ে?
মার্ক বুন

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

9

যখন setUp()পরীক্ষার শ্রেণীর একটি সুপারক্লাসে থাকে (উদাহরণস্বরূপ AbstractTestBaseনীচে), গৃহীত উত্তরটি নিম্নরূপে পরিবর্তন করা যেতে পারে:

public abstract class AbstractTestBase {
    private static Class<? extends AbstractTestBase> testClass;
    .....
    public void setUp() {
        if (this.getClass().equals(testClass)) {
            return;
        }

        // do the setup - once per concrete test class
        .....
        testClass = this.getClass();
    }
}

এটি একটি একক অ-স্থিতিশীল setUp()পদ্ধতির জন্য কাজ করা উচিত তবে tearDown()জটিল প্রতিবিম্বের বিশ্বে ভ্রষ্ট না হয়ে আমি এর সমমানের উত্পাদন করতে অক্ষম ... অনুগ্রহ করে যে যে কেউ পারে!


3

সম্পাদনা: আমি সবেমাত্র ডিবাগ করার সময় জানতে পারি যে ক্লাসটি প্রতিটি পরীক্ষার আগেই ইনস্ট্যান্ট হয় ated আমি অনুমান করি @ বিফার ক্লাস টীকাটি এখানে সেরা।

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

public UT () {
    // initialize once here
}
@Test
// Some test here...

পরীক্ষাগুলির আগে কর্টরকে ডাকা হবে কারণ সেগুলি অচল নয়।


0

এই সমাধানটি ব্যবহার করে দেখুন: https://stackoverflow.com/a/46274919/907576 :

সঙ্গে @BeforeAllMethods/ @AfterAllMethodsটীকা আপনি একটি দৃষ্টান্ত কনটেক্সট, যেখানে সব ইনজেকশনের মান পাওয়া যায় টেস্ট ক্লাসে কোন পদ্ধতি চালানো যেতে পারে।


একটি তৃতীয় পক্ষের লাইব্রেরিতে নির্ভর করে।
অ্যান্ড্রু

0

আমার নোংরা সমাধানটি হ'ল:

public class TestCaseExtended extends TestCase {

    private boolean isInitialized = false;
    private int serId;

    @Override
    public void setUp() throws Exception {
        super.setUp();
        if(!isInitialized) {
            loadSaveNewSerId();
            emptyTestResultsDirectory();
            isInitialized = true;
        }
    }

   ...

}

আমি এটি আমার সমস্ত পরীক্ষার কেসগুলির বেস বেস হিসাবে ব্যবহার করি।


পাবলিক ক্লাস টেস্ট কেস এক্সটেন্ডড টেস্ট কেস প্রসারিত করে {বেসরকারী স্ট্যাটিক বুলেটিয়ান আইসনিটালাইজড = মিথ্যা; প্রাইভেট স্ট্যাটিক টেস্টকেস এক্সটেন্ডেড কেস এক্সটেন্ডেড; প্রাইভেট ইন সিরিড; @ ওভাররাইড পাবলিক অকার্যকর সেটআপ () ছুঁড়ে ফেলেছে ব্যতিক্রম {সুপার.সেটআপ (); যদি (! isInitialized) {কেসএক্সেন্ডেড = নতুন টেস্টক্যাসএক্সেন্ডেড (); caseExtended.loadSaveNewSerId (); caseExtended.emptyTestResultsDirectory (); isInitialized = সত্য; }}
ওবি টু

0

আপনি যদি প্রতিটি সাবস্টেটে সেট এবং চেক করা হয় এমন একটি ভেরিয়েবলের জোর জবরদস্তি না করতে চান, তবে এটি একটি সুপারস্টেস্টে যুক্ত করতে পারে:

public abstract class SuperTest {

    private static final ConcurrentHashMap<Class, Boolean> INITIALIZED = new ConcurrentHashMap<>();
    protected final boolean initialized() {
        final boolean[] absent = {false};
        INITIALIZED.computeIfAbsent(this.getClass(), (klass)-> {
            return absent[0] = true;
        });
        return !absent[0];
    }
}



public class SubTest extends SuperTest {
    @Before
    public void before() {
        if ( super.initialized() ) return;

         ... magic ... 
    }

}

0

আমি এই সমস্যার সমাধান করেছি:

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

private static boolean started = false;
static{
    if (!started) {
        started = true;
        try {
            setUpDriver();  //method where you initialize your driver
        } catch (MalformedURLException e) {
        }
    }
}

এবং এখন, যদি আপনার পরীক্ষার শ্রেণীর প্রসারিত হবে বেজ বিমূর্ত বর্গ -> setUpDriver () পদ্ধতি আগে প্রথম @Test শুধুমাত্র মৃত্যুদন্ড কার্যকর করা হবে এক রান প্রতি সময়।


0

সমস্ত সূচনা কাজের জন্য বসন্তের @ পোষ্টকনস্ট্রাক্ট পদ্ধতিটি ব্যবহার করুন এবং @ টেস্টের কোনও কার্যকর হওয়ার আগে এই পদ্ধতিটি চলে

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