আমি কীভাবে নীচের কোডটিকে মক (টেবিলে, প্যাচ ডেকোরেটর এবং মাইকেল ফোর্ডের মক ফ্রেমওয়ার্ক দ্বারা সরবরাহিত সেন্ডিনেল ব্যবহার করে ) পরীক্ষা করব?
def testme(filepath):
with open(filepath, 'r') as f:
return f.read()
আমি কীভাবে নীচের কোডটিকে মক (টেবিলে, প্যাচ ডেকোরেটর এবং মাইকেল ফোর্ডের মক ফ্রেমওয়ার্ক দ্বারা সরবরাহিত সেন্ডিনেল ব্যবহার করে ) পরীক্ষা করব?
def testme(filepath):
with open(filepath, 'r') as f:
return f.read()
উত্তর:
এটি করার উপায়টি মক ০..0.০ এ পরিবর্তিত হয়েছে যা অবশেষে অজগর প্রোটোকল পদ্ধতিগুলি (যাদু পদ্ধতিগুলি), বিশেষত ম্যাজিকমক ব্যবহার করে বিদ্রূপকে সমর্থন করে:
http://www.voidspace.org.uk/python/mock/magicmock.html
প্রসঙ্গ পরিচালক হিসাবে বিদ্রূপের একটি উদাহরণ (মক ডকুমেন্টেশনের উদাহরণ পৃষ্ঠা থেকে):
>>> open_name = '%s.open' % __name__
>>> with patch(open_name, create=True) as mock_open:
... mock_open.return_value = MagicMock(spec=file)
...
... with open('/some/path', 'w') as f:
... f.write('something')
...
<mock.Mock object at 0x...>
>>> file_handle = mock_open.return_value.__enter__.return_value
>>> file_handle.write.assert_called_with('something')
__enter__
এবং __exit__
বস্তুগুলিকে বিদ্রূপ করার জন্য - পরবর্তী উত্তরটি কি পুরানো , নাকি এখনও কার্যকর?
file
গেছে!
mock_open
mock
কাঠামোর অংশ এবং এটি ব্যবহার করা খুব সহজ। patch
প্রসঙ্গ হিসাবে ব্যবহৃত প্যাচযুক্ত প্রতিস্থাপন করতে ব্যবহৃত বস্তুটি ফেরত দেয়: আপনি এটি পরীক্ষা সহজতর করতে এটি ব্যবহার করতে পারেন।
builtins
পরিবর্তে ব্যবহার করুন __builtin__
।
from unittest.mock import patch, mock_open
with patch("builtins.open", mock_open(read_data="data")) as mock_file:
assert open("path/to/open").read() == "data"
mock_file.assert_called_with("path/to/open")
mock
এর অংশ নয় unittest
এবং আপনার প্যাচ করা উচিত__builtin__
from mock import patch, mock_open
with patch("__builtin__.open", mock_open(read_data="data")) as mock_file:
assert open("path/to/open").read() == "data"
mock_file.assert_called_with("path/to/open")
আপনি যদি patch
সাজসজ্জার হিসাবে mock_open()
ফলাফলের ফলাফল হিসাবে ব্যবহার করেন তবে new
patch
এর যুক্তিটি কিছুটা অদ্ভুত হতে পারে।
এক্ষেত্রে new_callable
patch
যুক্তিটি ব্যবহার করা ভাল এবং মনে রাখবেন যে প্রতিটি অতিরিক্ত আর্গুমেন্ট যা patch
ব্যবহার করে না তা ডকুমেন্টেশনেnew_callable
বর্ণিত হিসাবে ফাংশনে পাস করা হবে ।patch
প্যাচ () নির্বিচারে কীওয়ার্ড আর্গুমেন্ট নেয়। এগুলি নির্মাণের জন্য মোক (বা নতুন_আপনযোগ্য) এ পাঠানো হবে।
উদাহরণস্বরূপ পাইথন ৩.x এর সজ্জিত সংস্করণটি হ'ল:
@patch("builtins.open", new_callable=mock_open, read_data="data")
def test_patch(mock_file):
assert open("path/to/open").read() == "data"
mock_file.assert_called_with("path/to/open")
মনে রাখবেন যে patch
এক্ষেত্রে আপনার পরীক্ষার ক্রিয়াকলাপটিকে তর্ক হিসাবে যুক্ত করা হবে।
with patch("builtins.open", mock_open(read_data="data")) as mock_file:
রূপান্তরকারী সিনট্যাক্সে রূপান্তর করা যায়? আমি চেষ্টা করেছি, তবে @patch("builtins.open", ...)
দ্বিতীয় তর্ক হিসাবে আমার কী দরকার তা আমি নিশ্চিত নই ।
return_value
এর mock_open
অন্য উপহাস বস্তুর মধ্যে এবং দ্বিতীয় উপহাস এর জাহির return_value
), কিন্তু এটি যোগ করে কাজ mock_open
যেমন new_callable
।
six
সামঞ্জস্যপূর্ণ mock
মডিউল পেতে আর্থারজপেলোরো মডিউলটিতে একবার নজর দিন । তবে আমি জানি না এটি builtins
কোনও সাধারণ মডিউলটিতেও ম্যাপ করে ।
মকের সর্বশেষতম সংস্করণগুলি সহ, আপনি সত্যিই দরকারী মক_পেন সহায়তা ব্যবহার করতে পারেন :
মক_পেন (উপহাস = কিছুই নয়, পঠিত_ডাটা = কোনওটি নয়)
খোলা ব্যবহার প্রতিস্থাপনের জন্য একটি উপকারী তৈরি করার জন্য একটি সহায়ক ফাংশন। এটি সরাসরি ডাকা বা কনটেক্সট ম্যানেজার হিসাবে ব্যবহৃত ওপেনের জন্য কাজ করে।
মক আর্গুমেন্টটি কনফিগার করার জন্য মক অবজেক্ট। যদি কিছুই না (ডিফল্ট) থাকে তবে স্ট্যান্ডার্ড ফাইল হ্যান্ডলগুলিতে উপলব্ধ পদ্ধতি বা বৈশিষ্ট্যগুলিতে সীমাবদ্ধ থাকা এপিআই দিয়ে আপনার জন্য একটি ম্যাজিকমক তৈরি করা হবে।
রিড_ডেটা ফাইল হ্যান্ডেলটি ফেরত পাঠানোর পদ্ধতির জন্য একটি স্ট্রিং। এটি ডিফল্টরূপে একটি খালি স্ট্রিং।
>>> from mock import mock_open, patch
>>> m = mock_open()
>>> with patch('{}.open'.format(__name__), m, create=True):
... with open('foo', 'w') as h:
... h.write('some stuff')
>>> m.assert_called_once_with('foo', 'w')
>>> handle = m()
>>> handle.write.assert_called_once_with('some stuff')
.write
কল আছে কিনা তা আপনি কীভাবে পরীক্ষা করবেন ?
handle.write.assert_any_call()
। handle.write.call_args_list
অর্ডারটি গুরুত্বপূর্ণ হলে আপনি প্রতিটি কল পেতে ব্যবহার করতে পারেন।
m.return_value.write.assert_called_once_with('some stuff')
ভাল ইমো। কল নিবন্ধন করা এড়ানো।
Mock.call_args_list
যে কোনওটিকে কল করার চেয়ে নিরাপদ Mock.assert_xxx
। আপনি যদি পরেরটি, মকের বৈশিষ্ট্য হিসাবে ভুল বানান করে থাকেন তবে সে সর্বদা নীরবে পাস করবে pass
একটি সাধারণ ফাইলের জন্য মক_পেন ব্যবহার করতে read()
( এই পৃষ্ঠায় ইতিমধ্যে প্রদত্ত আসল মক_পেন স্নিপেটটি লেখার জন্য আরও প্রস্তুত করা হয়েছে):
my_text = "some text to return when read() is called on the file object"
mocked_open_function = mock.mock_open(read_data=my_text)
with mock.patch("__builtin__.open", mocked_open_function):
with open("any_string") as f:
print f.read()
মক_পেনের জন্য দস্তাবেজ অনুসারে নোট করুন, এটি বিশেষত জন্য read()
, তাই for line in f
উদাহরণ হিসাবে উদাহরণ হিসাবে সাধারণ প্যাটার্নগুলির সাথে কাজ করবে না ।
পাইথন ২. 2...6 / উপহাস 1.0.1 ব্যবহার করে
for line in opened_file:
কোডের ধরণের সাহায্যে আমি এটি পেতে পারি না । আমি পুনরাবৃত্তিযোগ্য স্ট্রিংআইওর সাথে পরীক্ষার চেষ্টা করেছি যা প্রয়োগ করে __iter__
এবং এর পরিবর্তে এটি ব্যবহার করে my_text
, তবে ভাগ্য নেই।
read()
তাই এটি আপনার for line in opened_file
ক্ষেত্রে কাজ করবে না ; আমি স্পষ্ট করতে পোস্টটি সম্পাদনা করেছি
for line in f:
সমর্থন ফেরত মান উপহাস অর্জন করা সম্ভব open()
হিসাবে একটি StringIO পরিবর্তে আপত্তি ।
with open("any_string") as f: print f.read()
শীর্ষের উত্তরটি দরকারী তবে আমি এটির উপরে কিছুটা প্রসারিত করেছি।
আপনি যদি এখানে যাবেন তার একটি উপায় দিয়ে যুক্তিগুলির ভিত্তিতে আপনার ফাইল অবজেক্টের ( f
ইন as f
) মান নির্ধারণ করতে চান open()
:
def save_arg_return_data(*args, **kwargs):
mm = MagicMock(spec=file)
mm.__enter__.return_value = do_something_with_data(*args, **kwargs)
return mm
m = MagicMock()
m.side_effect = save_arg_return_array_of_data
# if your open() call is in the file mymodule.animals
# use mymodule.animals as name_of_called_file
open_name = '%s.open' % name_of_called_file
with patch(open_name, m, create=True):
#do testing here
মূলত, open()
কোনও বস্তু ফেরত দেবে এবং সেই বস্তুকে with
কল দেবে __enter__()
।
সঠিকভাবে উপহাস করার জন্য, open()
একটি মক অবজেক্ট ফেরত দেওয়ার জন্য আমাদের অবশ্যই বিদ্রূপ করা উচিত । সেই মক অবজেক্টটি তারপরে __enter__()
কলটিকে মক করতে হবে ( MagicMock
আমাদের জন্য এটি করবে) আমরা যে মক ডেটা / ফাইল অবজেক্টটি চাই সেগুলি ফিরিয়ে দিতে (অতএব mm.__enter__.return_value
)। উপরোক্ত উপায়ে 2 টি উপহাসের সাহায্যে এটি করা আমাদেরকে প্রদত্ত যুক্তিগুলি ক্যাপচার করতে open()
এবং সেগুলি আমাদের do_something_with_data
পদ্ধতিতে পাস করার অনুমতি দেয় ।
আমি স্ট্রিং হিসাবে একটি সম্পূর্ণ মক ফাইলটি পাস করেছি open()
এবং আমার do_something_with_data
চেহারাটি এর মতো দেখাচ্ছে:
def do_something_with_data(*args, **kwargs):
return args[0].split("\n")
এটি স্ট্রিংটিকে তালিকায় রূপান্তর করে যাতে আপনি সাধারণ ফাইলের সাথে নিম্নলিখিতগুলি করতে পারেন:
for line in file:
#do action
__enter__
? এটি অবশ্যই প্রস্তাবিত উপায়ের চেয়ে হ্যাকের মতো দেখতে আরও বেশি লাগে।
গেমটি হতে আমি কিছুটা দেরি করতে পারি, তবে কল করার সময় এটি আমার পক্ষে কাজ করে open
নতুন ফাইল তৈরি না করে অন্য মডিউলে এটি ।
test.py
import unittest
from mock import Mock, patch, mock_open
from MyObj import MyObj
class TestObj(unittest.TestCase):
open_ = mock_open()
with patch.object(__builtin__, "open", open_):
ref = MyObj()
ref.save("myfile.txt")
assert open_.call_args_list == [call("myfile.txt", "wb")]
MyObj.py
class MyObj(object):
def save(self, filename):
with open(filename, "wb") as f:
f.write("sample text")
মডিউলটির open
ভিতরে ফাংশনটি প্যাচ করে __builtin__
আমারmock_open()
কোনও ফাইল তৈরি না করেই মক করতে পারে।
দ্রষ্টব্য: আপনি যদি সাইথন ব্যবহার করে এমন কোনও মডিউল ব্যবহার করছেন বা আপনার প্রোগ্রামটি কোনওভাবেই সিথনের উপর নির্ভর করে তবে আপনার ফাইলের শীর্ষে অন্তর্ভুক্ত করে আপনাকে সাইথনের __builtin__
মডিউলটি আমদানি করতে হবে import __builtin__
। আপনি যদি __builtin__
সিথন ব্যবহার করছেন তবে আপনি সর্বজনীনকে উপহাস করতে পারবেন না ।
এটি একটি প্যাচগুলির জন্য একটি জসন কনফিগারেশন পড়ার জন্য কাজ করেছিল।
class ObjectUnderTest:
def __init__(self, filename: str):
with open(filename, 'r') as f:
dict_content = json.load(f)
ঠাট্টা করা বস্তুটি হ'ল io.TextIOWrapper অবজেক্টটি খোলা () ফাংশন দ্বারা ফিরে আসে
@patch("<src.where.object.is.used>.open",
return_value=io.TextIOWrapper(io.BufferedReader(io.BytesIO(b'{"test_key": "test_value"}'))))
def test_object_function_under_test(self, mocker):
আপনার যদি আর কোনও ফাইলের প্রয়োজন না হয় তবে আপনি পরীক্ষা পদ্ধতিটি সাজাইতে পারেন:
@patch('builtins.open', mock_open(read_data="data"))
def test_testme():
result = testeme()
assert result == "data"