আপনি কীভাবে পাইথনে গতিশীল (পরামিতি) ইউনিট পরীক্ষা তৈরি করবেন?


234

আমার কাছে এক ধরণের পরীক্ষার ডেটা রয়েছে এবং প্রতিটি আইটেমের জন্য একটি ইউনিট পরীক্ষা তৈরি করতে চাই। আমার প্রথম ধারণাটি এটির মতো করা ছিল:

import unittest

l = [["foo", "a", "a",], ["bar", "a", "b"], ["lee", "b", "b"]]

class TestSequence(unittest.TestCase):
    def testsample(self):
        for name, a,b in l:
            print "test", name
            self.assertEqual(a,b)

if __name__ == '__main__':
    unittest.main()

এর খারাপ দিকটি হ'ল এটি একটি পরীক্ষায় সমস্ত ডেটা পরিচালনা করে। আমি উড়ে প্রতিটি আইটেমের জন্য একটি পরীক্ষা জেনার চাই। কোনও পরামর্শ?



2
একটি ভাল লিঙ্ক যা একটি উত্তর সরবরাহ করতে পারে: eli.thegreenplace.net/2014/04/02/…
গৌরবময়

উত্তর:


173

একে "প্যারামেট্রাইজেশন" বলা হয়।

এই পদ্ধতির সমর্থন করে এমন বেশ কয়েকটি সরঞ্জাম রয়েছে। উদাহরণ:

ফলাফলযুক্ত কোডটি দেখতে এরকম দেখাচ্ছে:

from parameterized import parameterized

class TestSequence(unittest.TestCase):
    @parameterized.expand([
        ["foo", "a", "a",],
        ["bar", "a", "b"],
        ["lee", "b", "b"],
    ])
    def test_sequence(self, name, a, b):
        self.assertEqual(a,b)

যা পরীক্ষাগুলি উত্পন্ন করবে:

test_sequence_0_foo (__main__.TestSequence) ... ok
test_sequence_1_bar (__main__.TestSequence) ... FAIL
test_sequence_2_lee (__main__.TestSequence) ... ok

======================================================================
FAIL: test_sequence_1_bar (__main__.TestSequence)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "/usr/local/lib/python2.7/site-packages/parameterized/parameterized.py", line 233, in <lambda>
    standalone_func = lambda *a: func(*(a + p.args), **p.kwargs)
  File "x.py", line 12, in test_sequence
    self.assertEqual(a,b)
AssertionError: 'a' != 'b'

Reasonsতিহাসিক কারণে আমি আসল উত্তরটি প্রায় ২০০৮ এ ছেড়ে দেব):

আমি এই জাতীয় কিছু ব্যবহার:

import unittest

l = [["foo", "a", "a",], ["bar", "a", "b"], ["lee", "b", "b"]]

class TestSequense(unittest.TestCase):
    pass

def test_generator(a, b):
    def test(self):
        self.assertEqual(a,b)
    return test

if __name__ == '__main__':
    for t in l:
        test_name = 'test_%s' % t[0]
        test = test_generator(t[1], t[2])
        setattr(TestSequense, test_name, test)
    unittest.main()

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

1
@ কোডেপে প্রদত্ত উত্তর হিসাবে, নাক এটি পরিচালনা করে। তবে, নাক ইউনিকোড পরিচালনা করবে বলে মনে হয় না; সুতরাং আমার জন্য এটি একটি পছন্দসই সমাধান। +1
কিথ পিনসন

5
সুতরাং দ্রষ্টব্য, নকল প্রশ্নে আরও সঠিক উত্তর দেওয়া হয়েছে : stackoverflow.com/a/2799009/322020 - আপনি পরীক্ষা .__name__ =সক্ষম করতে ব্যবহার করতে পারেন.exact_method
নাকিলন

7
শ্রেণি সংশোধনকারী কোডটি if __name__ == '__main__'শর্তাধীন কেন উপস্থিত হয় ? অবশ্যই এটি আমদানির সময় চলার বাইরে এর বাইরে চলে যাওয়া উচিত (মনে রাখবেন পাইথন মডিউলগুলি কেবলমাত্র বিভিন্ন স্থান থেকে আমদানি করা হলেও একবারে আমদানি করা হয়)
SpoonMeiser

4
আমি মনে করি না এটি একটি ভাল সমাধান। ইউনিটেস্টের কোডটি যেভাবে কল হবে তার উপর নির্ভর করবে না। টেস্টকেসটি নাক বা পাইস্টে বা অন্য কোনও পরীক্ষার পরিবেশে ব্যবহারযোগ্য।
গেটলি

146

ইউনিটেস্ট ব্যবহার করে (৩.৪ থেকে)

পাইথন ৩.৪ থেকে স্ট্যান্ডার্ড গ্রন্থাগার unittestপ্যাকেজের subTestপ্রসঙ্গ পরিচালক রয়েছে।

ডকুমেন্টেশন দেখুন:

উদাহরণ:

from unittest import TestCase

param_list = [('a', 'a'), ('a', 'b'), ('b', 'b')]

class TestDemonstrateSubtest(TestCase):
    def test_works_as_expected(self):
        for p1, p2 in param_list:
            with self.subTest():
                self.assertEqual(p1, p2)

আপনি এখানে একটি কাস্টম বার্তা এবং পরামিতি মানগুলি নির্দিষ্ট করতে পারেন subTest():

with self.subTest(msg="Checking if p1 equals p2", p1=p1, p2=p2):

নাক ব্যবহার

নাক পরীক্ষামূলক ফ্রেমওয়ার্ক এই সমর্থন

উদাহরণ (নীচের কোডটি টেস্টযুক্ত ফাইলের সম্পূর্ণ বিষয়বস্তু):

param_list = [('a', 'a'), ('a', 'b'), ('b', 'b')]

def test_generator():
    for params in param_list:
        yield check_em, params[0], params[1]

def check_em(a, b):
    assert a == b

নাসকেস্ট কমান্ডের আউটপুট:

> nosetests -v
testgen.test_generator('a', 'a') ... ok
testgen.test_generator('a', 'b') ... FAIL
testgen.test_generator('b', 'b') ... ok

======================================================================
FAIL: testgen.test_generator('a', 'b')
----------------------------------------------------------------------
Traceback (most recent call last):
  File "/usr/lib/python2.5/site-packages/nose-0.10.1-py2.5.egg/nose/case.py", line 203, in runTest
    self.test(*self.arg)
  File "testgen.py", line 7, in check_em
    assert a == b
AssertionError

----------------------------------------------------------------------
Ran 3 tests in 0.006s

FAILED (failures=1)

3
এটি পরীক্ষার কেসগুলি গতিশীলরূপে উত্পন্ন করার একটি খুব পরিষ্কার উপায়।
চমত্কার

তবে সচেতন থাকুন, 'সেটআপ ()' জেনে নেবে না ফল দেওয়ার জন্য কী ভেরিয়েবল ব্যবহার করা হচ্ছে। প্রকৃতপক্ষে সেটআপ () জানতে পারবে না কী পরীক্ষা চলছে, বা পরীক্ষা_জেনেটর () এর ভিতরে ভারসেট সেট করা আছে। এটি সেটআপ () এর মধ্যে স্যানিটি পরীক্ষা করা জটিল করে তোলে এবং এটি কিছু কারণের দ্বারা পাইওয়াইস্টকে বেশি পছন্দ করে of
স্কট প্রাইভ

1
আপডেট বিভাগের জন্য আপভোটড। ঠিক আমার যা প্রয়োজন ছিল। :)
সৌরভ শ্রীবাস্তব

1
পাইস্টেস্টের সাথে ইউনিটেট সংস্করণ চালানোর কোনও উপায় আছে, যাতে এটি সমস্ত মামলা চালায় এবং প্রথম ব্যর্থ প্যারামিটারটি বন্ধ না করে?
kakk11

1
@ Kakk11 দ্বারা উল্লিখিত হিসাবে, এই উত্তরটি (এবং সাধারণভাবে সাব টেস্ট) পাইস্টের সাথে কাজ করে না। এটি একটি পরিচিত সমস্যা। এই কাজটি করার জন্য একটি সক্রিয়ভাবে বিকাশযুক্ত
Jérémie

76

এটি মেটাক্লাস ব্যবহার করে মার্জিতভাবে সমাধান করা যেতে পারে:

import unittest

l = [["foo", "a", "a",], ["bar", "a", "b"], ["lee", "b", "b"]]

class TestSequenceMeta(type):
    def __new__(mcs, name, bases, dict):

        def gen_test(a, b):
            def test(self):
                self.assertEqual(a, b)
            return test

        for tname, a, b in l:
            test_name = "test_%s" % tname
            dict[test_name] = gen_test(a,b)
        return type.__new__(mcs, name, bases, dict)

class TestSequence(unittest.TestCase):
    __metaclass__ = TestSequenceMeta

if __name__ == '__main__':
    unittest.main()

1
এটি সেলেনিয়ামের সাথে আমার জন্য দুর্দান্ত কাজ করেছে। একটি নোট হিসাবে, ক্লাসে টেস্টসেকুয়েন্সে আপনি "স্থিতিশীল" পদ্ধতিগুলি সেটআপ (স্ব), is_element_preferences (স্ব, কীভাবে, কী), ... টিয়ারডাউন (স্ব) এর মতো সংজ্ঞায়িত করতে পারেন। তাদের "পরে ফেলে ক্লাসের অধীনে একটি ক্লাস = TestSequenceMeta", বিবৃতি কাজ মনে হয়।
প্রেম এবং শান্তি - জো কোডসওয়েল

5
এই সমাধানটি গৃহীত আইএমএইচও হিসাবে নির্বাচিতটির চেয়ে ভাল।
পেট্রোস্ল্যাম্ব

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

11
দ্রষ্টব্য: অজগর 3 এ, এটিকে পরিবর্তন করুন:class TestSequence(unittest.TestCase, metaclass=TestSequenceMeta):[...]
ম্যাথিউ_ডু

3
আপনি দয়া করে dctপরিবর্তে ব্যবহার করতে পারেন dict? পরিবর্তনশীল নাম হিসাবে কীওয়ার্ড ব্যবহার করা বিভ্রান্তিকর এবং ত্রুটি-প্রবণ pr
npfoss

49

পাইথনের হিসাবে 3.4 সাবটসেটগুলি এই উদ্দেশ্যে ইউনিটেটে প্রবেশ করানো হয়েছে। বিশদ জন্য ডকুমেন্টেশন দেখুন । টেস্টকেস.সুবস্টেস্ট একটি প্রসঙ্গ ম্যানেজার যা পরীক্ষায় দৃser়তা আলাদা করতে দেয় যাতে পরামিতি তথ্যের সাথে ব্যর্থতার কথা জানানো যায় তবে পরীক্ষার কার্যকারিতা বন্ধ না করে। ডকুমেন্টেশন থেকে উদাহরণ এখানে:

class NumbersTest(unittest.TestCase):

def test_even(self):
    """
    Test that numbers between 0 and 5 are all even.
    """
    for i in range(0, 6):
        with self.subTest(i=i):
            self.assertEqual(i % 2, 0)

একটি পরীক্ষা রান আউটপুট হবে:

======================================================================
FAIL: test_even (__main__.NumbersTest) (i=1)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "subtests.py", line 32, in test_even
    self.assertEqual(i % 2, 0)
AssertionError: 1 != 0

======================================================================
FAIL: test_even (__main__.NumbersTest) (i=3)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "subtests.py", line 32, in test_even
    self.assertEqual(i % 2, 0)
AssertionError: 1 != 0

======================================================================
FAIL: test_even (__main__.NumbersTest) (i=5)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "subtests.py", line 32, in test_even
    self.assertEqual(i % 2, 0)
AssertionError: 1 != 0

এটি ইউনিটেস্ট 2 এরও একটি অংশ , তাই এটি পাইথনের পূর্ববর্তী সংস্করণগুলির জন্য উপলব্ধ।


1
অজগর ৩.৪ এবং এর চেয়ে বেশি ব্যবহার করা ভাল সমাধান।
ম্যাক্স ম্যালিশ

4
ইউনিটেস্ট ২ ব্যবহার করে এটি পাইথন ২.7 এর জন্যও উপলব্ধ।
বার্নহার্ড

11
এই পদ্ধতির এবং পৃথক পরীক্ষা গ্রহণের মধ্যে একটি প্রধান পার্থক্য হ'ল পরীক্ষার অবস্থা প্রতিবার পুনরায় সেট করা হয় না। (এটি, setUp()এবং tearDown()উপ-পরীক্ষার মধ্যে চালিত হয় না))
কেভিন ক্রিস্টোফার হেনরি

1
@ কেভিন ক্রিসটফার হেনরি হ্যাঁ, তবে self.setUp()তত্ত্বের মাধ্যমে সাবস্টেটের মধ্যে থেকেই ম্যানুয়ালি বলা যেতে পারে। হিসাবে tearDown, এটি শেষে স্বয়ংক্রিয়ভাবে কল করা যথেষ্ট হতে পারে।
একিউম্যানাস

আমি মনে করি যে উপরের মেটাক্লাস পদ্ধতির সাথে একত্রে ব্যবহৃত হলে এটি শক্তিশালী হতে পারে।
নাথন চ্যাপেল

36

লোড_সেটস একটি সামান্য পরিচিত প্রক্রিয়া যা 2.7 এ গতিশীলভাবে একটি টেস্টসুইট তৈরি করতে চালু হয়েছিল। এটির সাহায্যে আপনি সহজেই প্যারামিট্রাইজড পরীক্ষা তৈরি করতে পারেন।

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

import unittest

class GeneralTestCase(unittest.TestCase):
    def __init__(self, methodName, param1=None, param2=None):
        super(GeneralTestCase, self).__init__(methodName)

        self.param1 = param1
        self.param2 = param2

    def runTest(self):
        pass  # Test that depends on param 1 and 2.


def load_tests(loader, tests, pattern):
    test_cases = unittest.TestSuite()
    for p1, p2 in [(1, 2), (3, 4)]:
        test_cases.addTest(GeneralTestCase('runTest', p1, p2))
    return test_cases

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

বিকল্পভাবে, আপনি এই টিকিটে দেখানো হিসাবে উত্তরাধিকারও ব্যবহার করতে পারেন: http://bugs.python.org/msg151444


1
উপরের কোডটি ব্যর্থ হয়েছে: প্রকারের ত্রুটি: __init __ () সর্বাধিক 2 টি আর্গুমেন্ট নেয় (প্রদত্ত 4)
সর্বাধিক

2
নির্মাণকারীর অতিরিক্ত পরামিতিগুলিতে নাল ডিফল্ট যুক্ত হয়েছে।
জাভিয়ের

আমি @ মোজোর উত্তরে নাক-প্যারামিটারাইজ কোডটি পছন্দ করি তবে আমার ক্লায়েন্টদের জন্য এটি অতিরিক্ত নির্ভরতা এড়াতে খুব কার্যকর তাই আমি তাদের জন্য এটি ব্যবহার করব।
ঋষি

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

1
বোনাস: প্যারামে পাসের আউটপুটটির জন্য শর্ট ডেসক্রিপশন পদ্ধতিটি পুনরায় সংজ্ঞায়িত করার ক্ষমতা
মজাদার_ভিট

33

পাইস্টেস্ট ব্যবহার করে এটি করা যেতে পারে । test_me.pyবিষয়বস্তু দিয়ে কেবল ফাইলটি লিখুন :

import pytest

@pytest.mark.parametrize('name, left, right', [['foo', 'a', 'a'],
                                               ['bar', 'a', 'b'],
                                               ['baz', 'b', 'b']])
def test_me(name, left, right):
    assert left == right, name

এবং কমান্ড দিয়ে আপনার পরীক্ষা চালান py.test --tb=short test_me.py। তারপরে আউটপুটটি এমন দেখাচ্ছে:

=========================== test session starts ============================
platform darwin -- Python 2.7.6 -- py-1.4.23 -- pytest-2.6.1
collected 3 items

test_me.py .F.

================================= FAILURES =================================
_____________________________ test_me[bar-a-b] _____________________________
test_me.py:8: in test_me
    assert left == right, name
E   AssertionError: bar
==================== 1 failed, 2 passed in 0.01 seconds ====================

এটা সহজ! এছাড়াও pytest মত আরো বৈশিষ্ট্য আছে fixtures, mark, assert, ইত্যাদি ...


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

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

ধন্যবাদ। আমি সবেমাত্র unittestপাইস্টেস্টের দিকে যেতে শুরু করেছি। আমার কাছে TestCaseবেস ক্লাস ছিল যা গতিশীলভাবে বিভিন্ন যুক্তি দিয়ে বাচ্চাদের তৈরি করতে সক্ষম হয়েছিল যা তারা ক্লাস ভেরিয়েবল হিসাবে সংরক্ষণ করবে ... যা কিছুটা অনাস্থাপূর্ণ ছিল।
টিম্বেজ

1
@ টিমজেব হ্যাঁ আপনি ঠিক বলেছেন সবচেয়ে হত্যাকারী বৈশিষ্ট্য এর py.testরয়েছে yield_fixtures । যা সেটআপ করতে পারে , পরীক্ষায় কিছু দরকারী ডেটা ফিরিয়ে দেয় এবং টেস্ট শেষ হওয়ার পরে টিয়ারডাউন তৈরি করে । ফিক্সচারগুলিও প্যারামাইটাইজ করা যেতে পারে ।
সের্গেই ভোরোনজস্কি

12

ডিডিটি লাইব্রেরি ব্যবহার করুন । এটি পরীক্ষার পদ্ধতিগুলির জন্য সহজ সজ্জক যুক্ত করে:

import unittest
from ddt import ddt, data
from mycode import larger_than_two

@ddt
class FooTestCase(unittest.TestCase):

    @data(3, 4, 12, 23)
    def test_larger_than_two(self, value):
        self.assertTrue(larger_than_two(value))

    @data(1, -3, 2, 0)
    def test_not_larger_than_two(self, value):
        self.assertFalse(larger_than_two(value))

এই গ্রন্থাগারটি দিয়ে ইনস্টল করা যেতে পারে pip। এটির প্রয়োজন হয় না noseএবং স্ট্যান্ডার্ড লাইব্রেরি unittestমডিউলটির সাথে দুর্দান্ত কাজ করে ।


6

আপনি টেস্টসেনারিওস লাইব্রেরিটি ব্যবহার করে উপকৃত হবেন ।

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


5

হাইপোথিসিসও রয়েছে যা ফাজ বা সম্পত্তি ভিত্তিক পরীক্ষা যুক্ত করে: https://pypi.python.org/pypi/hypothesis

এটি একটি খুব শক্তিশালী পরীক্ষার পদ্ধতি।


আমি @given()ইউনিটেস্ট ক্লাসের ভিতরে ম্যাক্রো ব্যবহার করতে পারিনি ।
জন গ্রিন


4

আপনি নাক- ittr প্লাগইন ( pip install nose-ittr) ব্যবহার করতে পারেন ।

বিদ্যমান পরীক্ষাগুলির সাথে সংহত করা খুব সহজ, নূন্যতম পরিবর্তনগুলি (যদি থাকে তবে) প্রয়োজন required এটি নাকের মাল্টিপ্রসেসিং প্লাগইন সমর্থন করে ।

এমন নয় যে আপনি setupপরীক্ষায় প্রতি কাস্টমাইজ ফাংশনও রাখতে পারেন ।

@ittr(number=[1, 2, 3, 4])   
def test_even(self):   
    assert_equal(self.number % 2, 0)

nosetestতাদের বিল্ট-ইন প্লাগইনের মতো প্যারামিটারগুলি পাস করাও সম্ভব attrib, আপনি নির্দিষ্ট প্যারামিটার দিয়ে কেবলমাত্র একটি নির্দিষ্ট পরীক্ষা চালাতে পারবেন:

nosetest -a number=2

আমি এই পদ্ধতির পছন্দ করি, বিশেষত প্রতি পদ্ধতি স্তর এটি সমর্থন করে।
ম্যাট

3

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

আপনার উদাহরণ:

import unittest
from python_wrap_cases import wrap_case


@wrap_case
class TestSequence(unittest.TestCase):

    @wrap_case("foo", "a", "a")
    @wrap_case("bar", "a", "b")
    @wrap_case("lee", "b", "b")
    def testsample(self, name, a, b):
        print "test", name
        self.assertEqual(a, b)

কনসোল আউটপুট:

testsample_u'bar'_u'a'_u'b' (tests.example.test_stackoverflow.TestSequence) ... test bar
FAIL
testsample_u'foo'_u'a'_u'a' (tests.example.test_stackoverflow.TestSequence) ... test foo
ok
testsample_u'lee'_u'b'_u'b' (tests.example.test_stackoverflow.TestSequence) ... test lee
ok

এছাড়াও আপনি জেনারেটর ব্যবহার করতে পারেন । উদাহরণস্বরূপ এই কোডটি আর্গুমেন্ট a__listএবং এর সাথে পরীক্ষার সমস্ত সম্ভাব্য সংমিশ্রণ উত্পন্ন করেb__list

import unittest
from python_wrap_cases import wrap_case


@wrap_case
class TestSequence(unittest.TestCase):

    @wrap_case(a__list=["a", "b"], b__list=["a", "b"])
    def testsample(self, a, b):
        self.assertEqual(a, b)

কনসোল আউটপুট:

testsample_a(u'a')_b(u'a') (tests.example.test_stackoverflow.TestSequence) ... ok
testsample_a(u'a')_b(u'b') (tests.example.test_stackoverflow.TestSequence) ... FAIL
testsample_a(u'b')_b(u'a') (tests.example.test_stackoverflow.TestSequence) ... FAIL
testsample_a(u'b')_b(u'b') (tests.example.test_stackoverflow.TestSequence) ... ok

2

আমি জুড়ে এসেছিল ParamUnittest অন্য দিন যখন এ উত্স কোড দিকে তাকিয়ে রাডন ( GitHub রেপো উদাহরণ স্বরূপ ব্যবহার )। এটি টেস্ট কেস (নাকের মতো) প্রসারিত অন্যান্য ফ্রেমওয়ার্কগুলির সাথে কাজ করা উচিত।

এখানে একটি উদাহরণ:

import unittest
import paramunittest


@paramunittest.parametrized(
    ('1', '2'),
    #(4, 3),    <---- uncomment to have a failing test
    ('2', '3'),
    (('4', ), {'b': '5'}),
    ((), {'a': 5, 'b': 6}),
    {'a': 5, 'b': 6},
)
class TestBar(TestCase):
    def setParameters(self, a, b):
        self.a = a
        self.b = b

    def testLess(self):
        self.assertLess(self.a, self.b)

2
import unittest

def generator(test_class, a, b):
    def test(self):
        self.assertEqual(a, b)
    return test

def add_test_methods(test_class):
    #First element of list is variable "a", then variable "b", then name of test case that will be used as suffix.
    test_list = [[2,3, 'one'], [5,5, 'two'], [0,0, 'three']]
    for case in test_list:
        test = generator(test_class, case[0], case[1])
        setattr(test_class, "test_%s" % case[2], test)


class TestAuto(unittest.TestCase):
    def setUp(self):
        print 'Setup'
        pass

    def tearDown(self):
        print 'TearDown'
        pass

_add_test_methods(TestAuto)  # It's better to start with underscore so it is not detected as a test itself

if __name__ == '__main__':
    unittest.main(verbosity=1)

ফলাফল:

>>> 
Setup
FTearDown
Setup
TearDown
.Setup
TearDown
.
======================================================================
FAIL: test_one (__main__.TestAuto)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "D:/inchowar/Desktop/PyTrash/test_auto_3.py", line 5, in test
    self.assertEqual(a, b)
AssertionError: 2 != 3

----------------------------------------------------------------------
Ran 3 tests in 0.019s

FAILED (failures=1)

1
আপনার সঙ্গে মাইনর সমস্যা def add_test_methodsফাংশন। হওয়া উচিত def _add_test_methods আমি মনে করি
Raychaser

@ রায়চেসার ... আপনি ঠিক বলেছেন..আমি তা ঠিক করে ফেলেছি কিন্তু এখানে আপডেট করে নি .... তা ধরার জন্য ধন্যবাদ।
অরিন্দম রায়চৌধুরী

1

এখানে যেমন দেখা গেছে কেবল মেটাক্লাস ব্যবহার করুন;

class DocTestMeta(type):
    """
    Test functions are generated in metaclass due to the way some
    test loaders work. For example, setupClass() won't get called
    unless there are other existing test methods, and will also
    prevent unit test loader logic being called before the test
    methods have been defined.
    """
    def __init__(self, name, bases, attrs):
        super(DocTestMeta, self).__init__(name, bases, attrs)

    def __new__(cls, name, bases, attrs):
        def func(self):
            """Inner test method goes here"""
            self.assertTrue(1)

        func.__name__ = 'test_sample'
        attrs[func.__name__] = func
        return super(DocTestMeta, cls).__new__(cls, name, bases, attrs)

class ExampleTestCase(TestCase):
    """Our example test case, with no methods defined"""
    __metaclass__ = DocTestMeta

আউটপুট:

test_sample (ExampleTestCase) ... OK

1

আপনি ব্যবহার TestSuiteএবং কাস্টম TestCaseক্লাস করতে পারেন ।

import unittest

class CustomTest(unittest.TestCase):
    def __init__(self, name, a, b):
        super().__init__()
        self.name = name
        self.a = a
        self.b = b

    def runTest(self):
        print("test", self.name)
        self.assertEqual(self.a, self.b)

if __name__ == '__main__':
    suite = unittest.TestSuite()
    suite.addTest(CustomTest("Foo", 1337, 1337))
    suite.addTest(CustomTest("Bar", 0xDEAD, 0xC0DE))
    unittest.TextTestRunner().run(suite)

টেস্টসুয়েট কাজ করার সময়, আর্গুমেন্টগুলি __init__ফাংশন করার জন্য পাস হয় না ।
jadelord

1

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

import unittest

def rename(newName):
    def renamingFunc(func):
        func.__name__ == newName
        return func
    return renamingFunc

class TestGenerator(unittest.TestCase):

    TEST_DATA = {}

    @classmethod
    def generateTests(cls):
        for dataName, dataValue in TestGenerator.TEST_DATA:
            for func in cls.getTests(dataName, dataValue):
                setattr(cls, "test_{:s}_{:s}".format(func.__name__, dataName), func)

    @classmethod
    def getTests(cls):
        raise(NotImplementedError("This must be implemented"))

class TestCluster(TestGenerator):

    TEST_CASES = []

    @staticmethod
    def getTests(dataName, dataValue):

        def makeTest(case):

            @rename("{:s}".format(case["name"]))
            def test(self):
                # Do things with self, case, data
                pass

            return test

        return [makeTest(c) for c in TestCluster.TEST_CASES]

TestCluster.generateTests()

TestGeneratorবর্গ মত পরীক্ষার বিষয় বিভিন্ন সেট ডিম ব্যবহার করা যেতে পারেTestCluster

TestClusterTestGeneratorইন্টারফেসের প্রয়োগ হিসাবে বিবেচনা করা যেতে পারে ।


1

এই সমাধানটি পাইথন 2 এবং পাইথন 3 এর সাথে unittestএবং এর noseজন্য কাজ করে :

#!/usr/bin/env python
import unittest

def make_function(description, a, b):
    def ghost(self):
        self.assertEqual(a, b, description)
    print(description)
    ghost.__name__ = 'test_{0}'.format(description)
    return ghost


class TestsContainer(unittest.TestCase):
    pass

testsmap = {
    'foo': [1, 1],
    'bar': [1, 2],
    'baz': [5, 5]}

def generator():
    for name, params in testsmap.iteritems():
        test_func = make_function(name, params[0], params[1])
        setattr(TestsContainer, 'test_{0}'.format(name), test_func)

generator()

if __name__ == '__main__':
    unittest.main()

আপগ্রেড সংস্করণ <3 এর জন্য আপনাকে @ গিলিয়াম-জ্যাকুইনোট ধন্যবাদ!
এমপি

0

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

আমি এখানে যা এলাম তা এখানে:

import inspect
import types

test_platforms = [
    {'browserName': "internet explorer", 'platform': "Windows 7", 'version': "10.0"},
    {'browserName': "internet explorer", 'platform': "Windows 7", 'version': "11.0"},
    {'browserName': "firefox", 'platform': "Linux", 'version': "43.0"},
]


def sauce_labs():
    def wrapper(cls):
        return test_on_platforms(cls)
    return wrapper


def test_on_platforms(base_class):
    for name, function in inspect.getmembers(base_class, inspect.isfunction):
        if name.startswith('test_'):
            for platform in test_platforms:
                new_name = '_'.join(list([name, ''.join(platform['browserName'].title().split()), platform['version']]))
                new_function = types.FunctionType(function.__code__, function.__globals__, new_name,
                                                  function.__defaults__, function.__closure__)
                setattr(new_function, 'platform', platform)
                setattr(base_class, new_name, new_function)
            delattr(base_class, name)

    return base_class

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

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


0

মেটাক্লাস-ভিত্তিক উত্তরগুলি পাইথন 3 এ এখনও কাজ করে, তবে __metaclass__বৈশিষ্ট্যের পরিবর্তে একটিকে metaclassপ্যারামিটারটি ব্যবহার করতে হবে , যেমন:

class ExampleTestCase(TestCase,metaclass=DocTestMeta):
    pass

0

মেটা-প্রোগ্রামিং মজাদার, তবে পথে যেতে পারে। এখানে বেশিরভাগ সমাধান এটিকে কঠিন করে তোলে:

  • নির্বাচিতভাবে একটি পরীক্ষা চালু করুন
  • প্রদত্ত পরীক্ষার নামটি কোডটির দিকে ফিরে দেখান

সুতরাং, আমার প্রথম পরামর্শটি হল সহজ / স্পষ্ট পথ অনুসরণ করা (যে কোনও পরীক্ষার রানারের সাথে কাজ করে):

import unittest

class TestSequence(unittest.TestCase):

    def _test_complex_property(self, a, b):
        self.assertEqual(a,b)

    def test_foo(self):
        self._test_complex_property("a", "a")
    def test_bar(self):
        self._test_complex_property("a", "b")
    def test_lee(self):
        self._test_complex_property("b", "b")

if __name__ == '__main__':
    unittest.main()

যেহেতু আমাদের নিজেদের পুনরাবৃত্তি করা উচিত নয়, তাই আমার দ্বিতীয় পরামর্শটি @ জাভিয়েরের উত্তরের উপর ভিত্তি করে: সম্পত্তি ভিত্তিক পরীক্ষার আলিঙ্গন করুন। হাইপোথিসিস লাইব্রেরি:

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

    ক্লাস টেস্টসেকুয়েন্স (ইউনিটেস্ট.টেষ্টক্যাস):

    @given(st.text(), st.text())
    def test_complex_property(self, a, b):
        self.assertEqual(a,b)

আপনার নির্দিষ্ট উদাহরণ পরীক্ষা করতে, কেবল যুক্ত করুন:

    @example("a", "a")
    @example("a", "b")
    @example("b", "b")

শুধুমাত্র একটি নির্দিষ্ট উদাহরণ চালাতে, আপনি অন্যান্য উদাহরণগুলি মন্তব্য করতে পারেন (প্রদত্ত উদাহরণটি প্রথমে চালানো হবে)। আপনি ব্যবহার করতে পারেন@given(st.nothing()) । অন্য বিকল্পটি হ'ল সম্পূর্ণ ব্লকটি প্রতিস্থাপন করে:

    @given(st.just("a"), st.just("b"))

ঠিক আছে, আপনার পৃথক পরীক্ষার নাম নেই। তবে সম্ভবত আপনার প্রয়োজন:

  • পরীক্ষার অধীনে সম্পত্তি বর্ণনামূলক নাম।
  • যা ইনপুট ব্যর্থতার দিকে নিয়ে যায় (মিথ্যা উদাহরণ দেয়)।

মজাদার উদাহরণ


0

পার্টিতে দেরি হয়ে গেছে, তবে এই কাজগুলি করতে আমার খুব সমস্যা হয়েছিল setUpClass

এখানে @ জাভিয়েরের উত্তরের একটি সংস্করণ যা setUpClassগতিশীলভাবে বরাদ্দকৃত বৈশিষ্ট্যে অ্যাক্সেস দেয় ।

import unittest


class GeneralTestCase(unittest.TestCase):
    @classmethod
    def setUpClass(cls):
        print ''
        print cls.p1
        print cls.p2

    def runTest1(self):
        self.assertTrue((self.p2 - self.p1) == 1)

    def runTest2(self):
        self.assertFalse((self.p2 - self.p1) == 2)


def load_tests(loader, tests, pattern):
    test_cases = unittest.TestSuite()
    for p1, p2 in [(1, 2), (3, 4)]:
        clsname = 'TestCase_{}_{}'.format(p1, p2)
        dct = {
            'p1': p1,
            'p2': p2,
        }
        cls = type(clsname, (GeneralTestCase,), dct)
        test_cases.addTest(cls('runTest1'))
        test_cases.addTest(cls('runTest2'))
    return test_cases

আউটপুট

1
2
..
3
4
..
----------------------------------------------------------------------
Ran 4 tests in 0.000s

OK

0

শুধু মিশ্রণে অন্য একটি সমাধান নিক্ষেপ করতে;)

এটি কার্যকরভাবে parameterizedউপরে বর্ণিত মত একই , তবে সুনির্দিষ্ট unittest:

def sub_test(param_list):
    """Decorates a test case to run it as a set of subtests."""

    def decorator(f):

        @functools.wraps(f)
        def wrapped(self):
            for param in param_list:
                with self.subTest(**param):
                    f(self, **param)

        return wrapped

    return decorator

ব্যবহারের উদাহরণ:

class TestStuff(unittest.TestCase):
    @sub_test([
        dict(arg1='a', arg2='b'),
        dict(arg1='x', arg2='y'),
    ])
    def test_stuff(self, a, b):
        ...

-1

সেটেট্র ব্যবহারের পাশাপাশি আমরা পাইথন ৩.২ থেকে লোড_স্টেটগুলি ব্যবহার করতে পারি। অনুগ্রহ করে ব্লগ পোস্ট ব্লগ.লাইভেরো.com/en/coding/python/how-to-generate-discoverable-unit-tests-in-python-dnamically/ দেখুন

class Test(unittest.TestCase):
    pass

def _test(self, file_name):
    open(file_name, 'r') as f:
        self.assertEqual('test result',f.read())

def _generate_test(file_name):
    def test(self):
        _test(self, file_name)
    return test

def _generate_tests():
    for file in files:
        file_name = os.path.splitext(os.path.basename(file))[0]
        setattr(Test, 'test_%s' % file_name, _generate_test(file))

test_cases = (Test,)

def load_tests(loader, tests, pattern):
    _generate_tests()
    suite = TestSuite()
    for test_class in test_cases:
        tests = loader.loadTestsFromTestCase(test_class)
        suite.addTests(tests)
    return suite

if __name__ == '__main__':
    _generate_tests()
    unittest.main()

-1

নিম্নলিখিত আমার সমাধান। আমি এই দরকারীটি খুঁজে পাই যখন: ১. ইউনিটেস্টেস্টের জন্য কাজ করা উচিত est পরীক্ষা এবং ইউনিটেস্ট আবিষ্কার ২. বিভিন্ন পরামিতি সেটিংসের জন্য পরীক্ষা চালানোর জন্য একটি সেট রাখুন। ৩. খুব সহজেই অন্যান্য প্যাকেজগুলি আমদানির ইউনিটেস্টের উপর নির্ভরতা রাখে না

    class BaseClass(unittest.TestCase):
        def setUp(self):
            self.param = 2
            self.base = 2

        def test_me(self):
            self.assertGreaterEqual(5, self.param+self.base)

        def test_me_too(self):
            self.assertLessEqual(3, self.param+self.base)



     class Child_One(BaseClass):
        def setUp(self):
            BaseClass.setUp(self)
            self.param = 4


     class Child_Two(BaseClass):
        def setUp(self):
            BaseClass.setUp(self)
            self.param = 1

এটি প্রশ্নের উত্তর দেয় না, যা উড়ে পরীক্ষার উত্পন্ন করার বিষয়ে।
লেনজ

-1
import unittest

def generator(test_class, a, b,c,d,name):
    def test(self):
        print('Testexecution=',name)
        print('a=',a)
        print('b=',b)
        print('c=',c)
        print('d=',d)

    return test

def add_test_methods(test_class):
    test_list = [[3,3,5,6, 'one'], [5,5,8,9, 'two'], [0,0,5,6, 'three'],[0,0,2,3,'Four']]
    for case in test_list:
        print('case=',case[0], case[1],case[2],case[3],case[4])
        test = generator(test_class, case[0], case[1],case[2],case[3],case[4])
        setattr(test_class, "test_%s" % case[4], test)


class TestAuto(unittest.TestCase):
    def setUp(self):
        print ('Setup')
        pass

    def tearDown(self):
        print ('TearDown')
        pass

add_test_methods(TestAuto)

if __name__ == '__main__':
    unittest.main(verbosity=1)

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