আপনি ব্যবহার করছেন pytest
, যা আপনাকে ব্যর্থ পরীক্ষার সাথে ইন্টারঅ্যাক্ট করার জন্য পর্যাপ্ত বিকল্প দেয় gives এটি আপনাকে কমান্ড লাইন বিকল্পগুলি এবং এটি সম্ভব করার জন্য কয়েকটি হুক দেয়। আমি কীভাবে প্রতিটি ব্যবহার করব এবং আপনার নির্দিষ্ট ডিবাগিংয়ের প্রয়োজনীয়তার সাথে আপনি কাস্টমাইজেশন তৈরি করতে পারবেন তা আমি ব্যাখ্যা করব।
আমি আরও বেশি বিদেশী বিকল্পগুলির মধ্যে যাব যা আপনাকে নির্দিষ্ট দৃ as়তা সম্পূর্ণরূপে এড়িয়ে যাওয়ার অনুমতি দেয়, যদি আপনি সত্যিই মনে করেন যে আপনার অবশ্যই আবশ্যক।
জোর দেওয়া নয়, ব্যতিক্রমগুলি পরিচালনা করুন
নোট করুন যে একটি ব্যর্থ পরীক্ষা সাধারণত পাইস্টেস্ট বন্ধ করে না; কেবলমাত্র যদি আপনি স্পষ্টভাবে নির্দিষ্ট নম্বর ব্যর্থতার পরে প্রস্থান করতে স্পষ্টভাবে বলতে সক্ষম হন । এছাড়াও, পরীক্ষা ব্যর্থ হয় কারণ একটি ব্যতিক্রম উত্থাপিত হয়; assert
উত্থাপন করে AssertionError
তবে এটিই কেবল ব্যতিক্রম নয় যা পরীক্ষায় ব্যর্থ হতে পারে! আপনি কীভাবে ব্যতিক্রমগুলি পরিচালনা করা হয় তা নিয়ন্ত্রণ করতে চান, পরিবর্তিত হয় না assert
।
তবে, একটি ব্যর্থতা দৃ as় পৃথক পরীক্ষা শেষ হবে । এটি কারণ যে একবার try...except
ব্লকের বাইরে কোনও ব্যতিক্রম উত্থাপিত হলে পাইথন বর্তমান ফাংশন ফ্রেমটি উন্মুক্ত করে দেয় এবং এটির পিছনে আর ফিরে আসে না।
আমি মনে করি না যে এটি আপনি কী চান, আপনার _assertCustom()
দাবিটি পুনরায় চালনার আপনার বিবরণ দিয়ে বিচার করে তবে আমি আপনার বিকল্পগুলি আরও পরে আলোচনা করব।
পিডিবির সাথে পাইস্টে পোস্ট-মর্টেম ডিবাগিং
একটি ডিবাজারে ব্যর্থতাগুলি পরিচালনা করতে বিভিন্ন বিকল্পের জন্য, আমি --pdb
কমান্ড-লাইন সুইচ দিয়ে শুরু করব , যা কোনও পরীক্ষা ব্যর্থ হলে স্ট্যান্ডার্ড ডিবাগিং প্রম্পটটি খোলে (ব্রুটিটির জন্য আলাদাভাবে আউটপুট):
$ mkdir demo
$ touch demo/__init__.py
$ cat << EOF > demo/test_foo.py
> def test_ham():
> assert 42 == 17
> def test_spam():
> int("Vikings")
> EOF
$ pytest demo/test_foo.py --pdb
[ ... ]
test_foo.py:2: AssertionError
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> entering PDB >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
> /.../demo/test_foo.py(2)test_ham()
-> assert 42 == 17
(Pdb) q
Exit: Quitting debugger
[ ... ]
এই স্যুইচটি দিয়ে, যখন কোনও পরীক্ষা ব্যর্থ হয় তখন পাইস্টেস্ট পোস্ট-মর্টেম ডিবাগিং সেশন শুরু করে । এটি মূলত আপনি যা চেয়েছিলেন ঠিক তেমনই; একটি ব্যর্থ পরীক্ষার সময়ে কোডটি থামাতে এবং আপনার পরীক্ষার অবস্থার দিকে নজর দেওয়ার জন্য ডিবাগারটি খুলুন। আপনি পরীক্ষার স্থানীয় ভেরিয়েবলগুলি, গ্লোবালগুলি এবং স্ট্যাকের প্রতিটি ফ্রেমের স্থানীয় এবং গ্লোবালগুলির সাথে যোগাযোগ করতে পারেন।
এখানে পাইস্টেস্ট আপনাকে এই বিন্দুটির পরে প্রস্থান করা হবে কি না তার পুরো নিয়ন্ত্রণ দেয়: আপনি যদি q
প্রস্থান কমান্ডটি ব্যবহার করেন তবে পাইটেষ্ট রানটিও প্রস্থান করে, c
চালিয়ে যাওয়ার জন্য ব্যবহার করে পাইটেষ্টের নিয়ন্ত্রণ ফিরে আসবে এবং পরবর্তী পরীক্ষাটি কার্যকর করা হবে।
বিকল্প ডিবাগার ব্যবহার করা
আপনি pdb
এটির জন্য ডিবাগারে আবদ্ধ নন ; আপনি --pdbcls
স্যুইচ দিয়ে একটি ভিন্ন ডিবাগার সেট করতে পারেন। কোন pdb.Pdb()
সামঞ্জস্যপূর্ণ বাস্তবায়ন কাজ করবে সহ IPython ডিবাগার বাস্তবায়ন , বা অন্যান্য অধিকাংশ পাইথন debuggers ( pudb ডিবাগার প্রয়োজন -s
সুইচ ব্যবহার করা হয়, অথবা একটি বিশেষ প্লাগইন )। স্যুইচটি একটি মডিউল এবং বর্গ নেয়, উদাহরণস্বরূপ আপনি ব্যবহার pudb
করতে পারেন এমন ব্যবহার করতে:
$ pytest -s --pdb --pdbcls=pudb.debugger:Debugger
আপনি এই বৈশিষ্ট্যটি চারপাশে আপনার নিজের র্যাপার ক্লাস লিখতে ব্যবহার করতে Pdb
পারেন যা নির্দিষ্ট ব্যর্থতা আপনার আগ্রহী কিছু না হলে কেবল তাত্ক্ষণিকভাবে ফিরে আসে like ঠিক যেমনটি pytest
ব্যবহার করে :Pdb()
pdb.post_mortem()
p = Pdb()
p.reset()
p.interaction(None, t)
এখানে, t
একটি ট্রেসব্যাক অবজেক্ট । যখন p.interaction(None, t)
ফিরে আসে, pytest
পরবর্তী পরীক্ষা দিয়ে চালিয়ে যান, যদি না p.quitting
সেট করা থাকেTrue
(যারপরে পাইস্টেস্টটি প্রস্থান করে)।
এখানে একটি উদাহরণ বাস্তবায়ন যা মুদ্রণ করে যে আমরা ডিবাগ করতে অস্বীকার করছি এবং অবিলম্বে ফিরে আসবে, যদি না পরীক্ষাটি উত্থাপিত না হয় তবে ValueError
সংরক্ষণ করা হয় demo/custom_pdb.py
:
import pdb, sys
class CustomPdb(pdb.Pdb):
def interaction(self, frame, traceback):
if sys.last_type is not None and not issubclass(sys.last_type, ValueError):
print("Sorry, not interested in this failure")
return
return super().interaction(frame, traceback)
আমি যখন উপরের ডেমো দিয়ে এটি ব্যবহার করি, এটি আউটপুট (আবার, ব্রেভিটির জন্য আলাদা):
$ pytest test_foo.py -s --pdb --pdbcls=demo.custom_pdb:CustomPdb
[ ... ]
def test_ham():
> assert 42 == 17
E assert 42 == 17
test_foo.py:2: AssertionError
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> entering PDB >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
Sorry, not interested in this failure
F
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> traceback >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
def test_spam():
> int("Vikings")
E ValueError: invalid literal for int() with base 10: 'Vikings'
test_foo.py:4: ValueError
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> entering PDB >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
> /.../test_foo.py(4)test_spam()
-> int("Vikings")
(Pdb)
sys.last_type
ব্যর্থতাটি 'আকর্ষণীয়' কিনা তা নির্ধারণ করার জন্য উপরের অন্তর্নির্ধারণগুলি ।
তবে, আপনি tkInter বা অনুরূপ কিছু ব্যবহার করে নিজের ডিবাগারটি লিখতে না চাইলে আমি সত্যিই এই বিকল্পটির সুপারিশ করতে পারি না। নোট করুন যে এটি একটি বড় উদ্যোগ।
ফিল্টারিং ব্যর্থতা; ডিবাগারটি কখন খুলবেন তা চয়ন করুন
পরবর্তী স্তরটি হ'ল পাইস্ট ডিবাগিং এবং ইন্টারঅ্যাকশন হুক ; এগুলি হাইড পয়েন্টগুলি হ'ল আচরণ কাস্টমাইজেশনের জন্য, পাইটেষ্ট কীভাবে সাধারণত কোনও ব্যতিক্রম পরিচালনা করে বা ডিবাগারে প্রবেশ করে pdb.set_trace()
বা breakpoint()
(পাইথন ৩.7 বা আরও নতুন) এর মতো জিনিসগুলি পরিচালনা করে তা বাড়ানোর জন্য ।
এই হুকটির অভ্যন্তরীণ বাস্তবায়ন >>> entering PDB >>>
উপরের ব্যানারটিও প্রিন্ট করার জন্য দায়ী , সুতরাং ডিবাগারটি চালানো থেকে রোধ করতে এই হুকটি ব্যবহার করার অর্থ আপনি এই আউটপুটটি মোটেও দেখতে পাবেন না। পরীক্ষার ব্যর্থতা যখন 'আকর্ষণীয়' হয় তখন আপনার নিজের হুকটি মূল হুকটিতে ডেলিগেট করতে পারে এবং সুতরাং আপনি যে ডিবাগারটি ব্যবহার করছেন তার থেকে পৃথক ফিল্টার পরীক্ষার ব্যর্থতা ! আপনি নাম দ্বারা এটি অ্যাক্সেস করে অভ্যন্তরীণ বাস্তবায়ন অ্যাক্সেস করতে পারেন ; এর জন্য অভ্যন্তরীণ হুক প্লাগইনটির নাম দেওয়া হয়েছে pdbinvoke
। এটি চালানো থেকে রোধ করতে আপনার এটিকে নিবন্ধভুক্ত করতে হবে তবে একটি রেফারেন্স সংরক্ষণ করুন আমরা কীভাবে এটি প্রয়োজন হিসাবে সরাসরি কল করতে পারি।
এখানে যেমন একটি হুক একটি নমুনা বাস্তবায়ন; প্লাগিনগুলি লোড হওয়া যে কোনও অবস্থানের মধ্যে আপনি এটি রাখতে পারেন ; আমি এটি ভিতরে রাখা demo/conftest.py
:
import pytest
@pytest.hookimpl(trylast=True)
def pytest_configure(config):
# unregister returns the unregistered plugin
pdbinvoke = config.pluginmanager.unregister(name="pdbinvoke")
if pdbinvoke is None:
# no --pdb switch used, no debugging requested
return
# get the terminalreporter too, to write to the console
tr = config.pluginmanager.getplugin("terminalreporter")
# create or own plugin
plugin = ExceptionFilter(pdbinvoke, tr)
# register our plugin, pytest will then start calling our plugin hooks
config.pluginmanager.register(plugin, "exception_filter")
class ExceptionFilter:
def __init__(self, pdbinvoke, terminalreporter):
# provide the same functionality as pdbinvoke
self.pytest_internalerror = pdbinvoke.pytest_internalerror
self.orig_exception_interact = pdbinvoke.pytest_exception_interact
self.tr = terminalreporter
def pytest_exception_interact(self, node, call, report):
if not call.excinfo. errisinstance(ValueError):
self.tr.write_line("Sorry, not interested!")
return
return self.orig_exception_interact(node, call, report)
উপরের প্লাগইনটি টার্মিনালে লাইন লিখতে অভ্যন্তরীণ TerminalReporter
প্লাগইন ব্যবহার করে; এটি ডিফল্ট কমপ্যাক্ট পরীক্ষার স্থিতি বিন্যাস ব্যবহার করার সময় আউটপুট ক্লিনার করে তোলে এবং আউটপুট ক্যাপচারিং সক্ষম করেও আপনাকে টার্মিনালে জিনিস লিখতে দেয়।
উদাহরণটি pytest_exception_interact
অন্য হুকের মাধ্যমে হুকের সাহায্যে প্লাগইন অবজেক্টটিকে নিবন্ধভুক্ত করে pytest_configure()
, তবে @pytest.hookimpl(trylast=True)
অভ্যন্তরীণ pdbinvoke
প্লাগইনটিকে নিবন্ধভুক্ত করতে সক্ষম হতে এটি যথেষ্ট দেরিতে (ব্যবহার করে ) চালিয়ে যায় তা নিশ্চিত করে । যখন হুক বলা হয়, উদাহরণটি call.exceptinfo
বস্তুর বিরুদ্ধে পরীক্ষা করে ; আপনি নোড বা রিপোর্টটিও পরীক্ষা করতে পারেন ।
উপরোক্ত নমুনা কোডটি স্থানে রেখে demo/conftest.py
, test_ham
পরীক্ষার ব্যর্থতা উপেক্ষা করা হয়, কেবল test_spam
পরীক্ষার ব্যর্থতা, যা উত্থাপিত হয় ValueError
, ফলাফলটি ডিবাগ প্রম্পট খোলার ফলে:
$ pytest demo/test_foo.py --pdb
[ ... ]
demo/test_foo.py F
Sorry, not interested!
demo/test_foo.py F
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> traceback >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
def test_spam():
> int("Vikings")
E ValueError: invalid literal for int() with base 10: 'Vikings'
demo/test_foo.py:4: ValueError
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> entering PDB >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
> /.../demo/test_foo.py(4)test_spam()
-> int("Vikings")
(Pdb)
পুনরায় পুনরাবৃত্তি করতে, উপরোক্ত পদ্ধতির অতিরিক্ত সুবিধা রয়েছে যা আপনি এটি কোনও পুডব বা আইপথন ডিবাগার সহ পাইটেষ্টের সাথে কাজ করে এমন কোনও ডিবাগারের সাথে একত্রিত করতে পারেন :
$ pytest demo/test_foo.py --pdb --pdbcls=IPython.core.debugger:Pdb
[ ... ]
demo/test_foo.py F
Sorry, not interested!
demo/test_foo.py F
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> traceback >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
def test_spam():
> int("Vikings")
E ValueError: invalid literal for int() with base 10: 'Vikings'
demo/test_foo.py:4: ValueError
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> entering PDB >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
> /.../demo/test_foo.py(4)test_spam()
1 def test_ham():
2 assert 42 == 17
3 def test_spam():
----> 4 int("Vikings")
ipdb>
কী পরীক্ষা চলছিল ( node
যুক্তির মাধ্যমে ) এবং উত্থাপিত ব্যতিক্রমটির প্রত্যক্ষ অ্যাক্সেস ( call.excinfo
ExceptionInfo
উদাহরণের মাধ্যমে) সম্পর্কে এটির আরও অনেক প্রসঙ্গ রয়েছে ।
নোট করুন যে নির্দিষ্ট পাইস্টেস্ট ডিবাগার প্লাগইনগুলি (যেমন pytest-pudb
বা pytest-pycharm
) তাদের নিজস্ব pytest_exception_interact
হুকস্প্প নিবন্ধন করে । প্রতিটি সম্পূর্ণ প্লাগইন ব্যবহার করে config.pluginmanager.list_name_plugin
এবং hasattr()
পরীক্ষার জন্য স্বেচ্ছাসেবী প্লাগইনগুলি ওভাররাইড করতে প্লাগইন-ম্যানেজারের সমস্ত প্লাগইনকে আরও সম্পূর্ণ বাস্তবায়ন করতে হবে over
ব্যর্থতা পুরোপুরি চলে যায়
এটি আপনাকে ব্যর্থ টেস্ট ডিবাগিংয়ের উপরে পুরোপুরি নিয়ন্ত্রণ প্রদান করার পরে, যদি আপনি প্রদত্ত পরীক্ষার জন্য ডিবাগারটি না খোলার জন্য পছন্দ না করেও এটি পরীক্ষাকে ব্যর্থ হিসাবে ফেলে দেয় । আপনি ব্যর্থতা পুরাপুরি দূরে যেতে করতে চান, আপনি ব্যবহার একটি আলাদা হুক করতে পারেন: pytest_runtest_call()
।
পাইস্টেস্ট পরীক্ষা চালালে, এটি উপরের হুকের মাধ্যমে পরীক্ষা চালাবে, যা প্রত্যাশিত None
বা ব্যতিক্রম বাড়াতে পারে । এটি থেকে একটি প্রতিবেদন তৈরি করা হয়, allyচ্ছিকভাবে একটি লগ এন্ট্রি তৈরি করা হয়, এবং যদি পরীক্ষাটি ব্যর্থ হয়, তবে পূর্বোক্ত pytest_exception_interact()
হুক বলা হবে। সুতরাং আপনাকে যা করতে হবে তা হুক এর ফলশ্রুতিতে ফলাফলটি পরিবর্তন করে; ব্যতিক্রম পরিবর্তে এটি কিছুতেই ফিরে আসা উচিত নয়।
এটি করার সর্বোত্তম উপায় হুক র্যাপার ব্যবহার করা । হুক মোড়কের আসল কাজটি করতে হবে না, তবে পরিবর্তে হুকের ফলাফলের সাথে কী ঘটে তা পরিবর্তনের সুযোগ দেওয়া হয়। আপনাকে যা করতে হবে তা হ'ল লাইনটি যুক্ত করুন:
outcome = yield
আপনার হুক মোড়ক বাস্তবায়নে এবং আপনি মাধ্যমে পরীক্ষার ব্যতিক্রম সহ হুক ফলাফলের অ্যাক্সেস পাবেন outcome.excinfo
। পরীক্ষায় কোনও ব্যতিক্রম উত্থাপিত হলে এই বৈশিষ্ট্যটি (টাইপ, উদাহরণ, ট্রেসব্যাক) এর একটি টিপলকে সেট করা হয়। বিকল্পভাবে, আপনি কল করতে পারেন outcome.get_result()
এবং স্ট্যান্ডার্ড try...except
হ্যান্ডলিং ব্যবহার করতে পারেন ।
তাহলে আপনি কীভাবে ব্যর্থ পরীক্ষার পাস করবেন? আপনার কাছে 3 টি বেসিক বিকল্প রয়েছে:
- আপনি মোড়কে কল করে পরীক্ষাকে প্রত্যাশিত ব্যর্থতা হিসাবে চিহ্নিত করতে পারেন
pytest.xfail()
।
- আপনি আইটেমটি এড়িয়ে গেছেন হিসাবে চিহ্নিত করতে পারেন , যা ভান করে যে কলটি করার মাধ্যমে পরীক্ষাটি প্রথম স্থানে কখনও চালানো হয়নি
pytest.skip()
।
- আপনি
outcome.force_result()
পদ্ধতিটি ব্যবহার করে ব্যতিক্রমটি সরিয়ে ফেলতে পারেন ; ফলাফলটি এখানে একটি খালি তালিকায় সেট করুন (যার অর্থ: নিবন্ধিত হুক ছাড়া আর কিছুই তৈরি হয়নি None
) এবং ব্যতিক্রমটি পুরোপুরি সাফ হয়ে যায়।
আপনি যা ব্যবহার করেন তা আপনার উপর নির্ভর করে। প্রথমে এড়িয়ে যাওয়া এবং প্রত্যাশিত-ব্যর্থতা পরীক্ষার জন্য ফলাফলটি পরীক্ষা করে নেওয়ার বিষয়টি নিশ্চিত করে নিন যেহেতু আপনাকে সেইগুলি কেসগুলি হ্যান্ডেল করার দরকার নেই যেমন পরীক্ষাটি ব্যর্থ হয়েছে। এই বিকল্পগুলি pytest.skip.Exception
এবং এর মাধ্যমে উত্থাপিত বিশেষ ব্যতিক্রমগুলি আপনি অ্যাক্সেস করতে পারেন pytest.xfail.Exception
।
এখানে একটি উদাহরণ বাস্তবায়ন যা চিহ্ন পরীক্ষা করে বাড়তে দেবেন না ব্যর্থ ValueError
, যেমন এড়ানো :
import pytest
@pytest.hookimpl(hookwrapper=True)
def pytest_runtest_call(item):
outcome = yield
try:
outcome.get_result()
except (pytest.xfail.Exception, pytest.skip.Exception, pytest.exit.Exception):
raise # already xfailed, skipped or explicit exit
except ValueError:
raise # not ignoring
except (pytest.fail.Exception, Exception):
# turn everything else into a skip
pytest.skip("[NOTRUN] ignoring everything but ValueError")
conftest.py
আউটপুট স্থাপন করা হয় যখন :
$ pytest -r a demo/test_foo.py
============================= test session starts =============================
platform darwin -- Python 3.8.0, pytest-3.10.0, py-1.7.0, pluggy-0.8.0
rootdir: ..., inifile:
collected 2 items
demo/test_foo.py sF [100%]
=================================== FAILURES ===================================
__________________________________ test_spam ___________________________________
def test_spam():
> int("Vikings")
E ValueError: invalid literal for int() with base 10: 'Vikings'
demo/test_foo.py:4: ValueError
=========================== short test summary info ============================
FAIL demo/test_foo.py::test_spam
SKIP [1] .../demo/conftest.py:12: [NOTRUN] ignoring everything but ValueError
===================== 1 failed, 1 skipped in 0.07 seconds ======================
আমি -r a
পতাকাটি পরিষ্কার করার জন্য ব্যবহার করেছি যা test_ham
এখন এড়িয়ে গেছে।
আপনি যদি pytest.skip()
কলটির সাথে প্রতিস্থাপন করেন pytest.xfail("[XFAIL] ignoring everything but ValueError")
, পরীক্ষাটি প্রত্যাশিত ব্যর্থতা হিসাবে চিহ্নিত করা হয়:
[ ... ]
XFAIL demo/test_foo.py::test_ham
reason: [XFAIL] ignoring everything but ValueError
[ ... ]
এবং outcome.force_result([])
এটি পাস হিসাবে চিহ্নিত ব্যবহার :
$ pytest -v demo/test_foo.py # verbose to see individual PASSED entries
[ ... ]
demo/test_foo.py::test_ham PASSED [ 50%]
আপনার ব্যবহারের ক্ষেত্রে এটির ক্ষেত্রে সবচেয়ে বেশি উপযুক্ত যা আপনার মনে হয়। এর জন্য skip()
এবং xfail()
আমি স্ট্যান্ডার্ড বার্তা ফর্ম্যাটটি অনুকরণ করেছি (এর সাথে উপসর্গযুক্ত [NOTRUN]
বা [XFAIL]
) তবে আপনি চান অন্য কোনও বার্তা ফর্ম্যাটটি ব্যবহার করতে পারবেন না।
তিনটি ক্ষেত্রেই পাইস্টেস্ট পরীক্ষার জন্য ডিবাগারটি খুলবে না যার ফলাফল আপনি এই পদ্ধতিটি ব্যবহার করে পরিবর্তন করেছেন।
পৃথক দাবী বিবৃতি পরিবর্তন
আপনি যদি কোনওassert
পরীক্ষার মধ্যে পরীক্ষাগুলি পরিবর্তন করতে চান তবে আপনি আরও অনেক বেশি কাজের জন্য নিজেকে সেট আপ করছেন। হ্যাঁ, এটি প্রযুক্তিগতভাবে সম্ভব, তবে পাইথন সংকলনের সময় যে কোডটি কার্যকর করতে চলেছে কেবল তা আবার লিখে দিয়ে ।
আপনি যখন ব্যবহার করবেন pytest
, এটি ইতিমধ্যে ইতিমধ্যে করা হচ্ছে । Pytest নতুন করে লেখা হয় assert
আপনি আরো কনটেক্সট দিতে যখন আপনার দাবি ব্যর্থ বিবৃতি ; ঠিক কী করা হচ্ছে তার পাশাপাশি উত্স কোডের একটি ভাল ওভারভিউয়ের জন্য এই ব্লগ পোস্টটি দেখুন । নোট করুন যে মডিউলটি 1k লাইনের বেশি লম্বা, এবং পাইথনের বিমূর্ত সিনট্যাক্স ট্রি কীভাবে কাজ করে তা আপনার বুঝতে হবে । যদি আপনি এটি করেন তবে আপনি কোনও হ্যান্ডলারের সাথে পার্শ্ববর্তীসহ নিজের নিজস্ব পরিবর্তনগুলি যুক্ত করতে সেখানে সেই মডিউলটি বানরপ্যাচ করতে পারেন ।_pytest/assertion/rewrite.py
assert
try...except AssertionError:
তবে , আপনি কেবলমাত্র নির্বাচনগুলি যথাযথভাবে অক্ষম বা অগ্রাহ্য করতে পারবেন না, কারণ পরবর্তী বিবৃতিগুলি সহজেই রাষ্ট্রের (নির্দিষ্ট অবজেক্টের বিন্যাস, ভেরিয়েবল সেট ইত্যাদি) উপর নির্ভর করতে পারে যা একটি এড়িয়ে যাওয়া দাবির বিরুদ্ধে রক্ষা করা ছিল। যদি কোনও জোর পরীক্ষা foo
না হয় None
তবে পরে যুক্তিটি foo.bar
অস্তিত্বের উপর নির্ভর করে , তবে আপনি কেবল AttributeError
সেখানে চলে যাবেন ইত্যাদি the ব্যতিক্রমটিকে পুনরায় উত্থাপন করতে আটকে থাকুন, যদি আপনাকে এই পথে যেতে হয় তবে need
আমি asserts
এখানে পুনরায় লেখার বিষয়ে আরও বিশদে যেতে যাচ্ছি না , কারণ আমি মনে করি না যে এটি অনুসরণ করা উপযুক্ত, এতে জড়িত কাজের পরিমাণ দেওয়া হয়নি এবং পোস্ট-মর্টেম ডিবাগিংয়ের সাথে পরীক্ষার রাজ্যে আপনাকে অ্যাক্সেস প্রদান করবে দৃ failure়তা ব্যর্থতা যাইহোক বিন্দু ।
নোট করুন যে আপনি যদি এটি করতে চান তবে আপনার ব্যবহারের দরকার নেই eval()
(যা কোনওভাবেই কাজ করবে না, assert
এটি একটি বিবৃতি, সুতরাং এর exec()
পরিবর্তে আপনার ব্যবহারের দরকার হবে), অথবা আপনাকে দু'বার দাবি চালাতে হবে না (যা কোনটি নয়) দৃ the়তা পরিবর্তিত অবস্থায় যদি অভিব্যক্তিটি ব্যবহৃত হয় তবে বিষয়টি নিয়ে যেতে পারে। আপনি পরিবর্তে ast.Assert
নোডের ভিতরে নোড এম্বেড করবেন ast.Try
এবং একটি ফাঁকা ast.Raise
নোড ব্যবহার করে এমন একটি হ্যান্ডলার সংযুক্ত করবেন যা ধরা পড়েছিল এমন ব্যতিক্রম পুনরায় উত্থাপন করবে।
দৃser় বিবৃতি এড়ানোর জন্য ডিবাগার ব্যবহার করে।
পাইথন ডিবাগার আসলে / কমান্ড ব্যবহার করে আপনাকে বিবৃতি এড়িয়ে যেতে দেয় । আপনি কি জানেন সামনে যা নির্দিষ্ট কোনো বিবৃতি হবে ব্যর্থ, আপনি এটি বাইপাস এই ব্যবহার করতে পারেন। আপনি আপনার পরীক্ষাগুলি দিয়ে চালাতে পারেন , যা প্রতিটি পরীক্ষার শুরুতে ডিবাগারটি খোলায় , তারপরে ডিবাগারটি যখন দাবী করার ঠিক আগে থামিয়ে দেওয়া হয় তখন এটিকে এড়িয়ে যেতে একটি ইস্যু করুন ।j
jump
--trace
j <line after assert>
আপনি এটি স্বয়ংক্রিয় করতে পারেন। উপরের কৌশলগুলি ব্যবহার করে আপনি একটি কাস্টম ডিবাগার প্লাগইন তৈরি করতে পারেন
- ব্যতিক্রম
pytest_testrun_call()
ধরতে হুক ব্যবহার করেAssertionError
- ট্রেসব্যাকটি থেকে 'আপত্তিকর' লাইন নম্বরটি বের করে এবং সম্ভবত কিছু উত্স কোড বিশ্লেষণের মাধ্যমে একটি সফল জাম্প চালানোর জন্য প্রয়োজনীয় দৃ the়তার আগে এবং পরে লাইন নম্বরগুলি নির্ধারণ করে
- আবার পরীক্ষা চালায় , তবে এবার একটি
Pdb
সাবক্লাস ব্যবহার করে যা দৃsert়তার আগে লাইনে একটি ব্রেকপয়েন্ট নির্ধারণ করে এবং ব্রেকপয়েন্টটি আঘাত হানার পরে স্বয়ংক্রিয়ভাবে দ্বিতীয়টিতে একটি লাফ চালায় এবং তারপরে একটি c
চালিয়ে যেতে হবে।
অথবা, ব্যর্থ হওয়ার জন্য একটি দৃ to়তার জন্য অপেক্ষা করার পরিবর্তে, আপনি assert
পরীক্ষায় প্রাপ্ত প্রতিটিটির জন্য ব্রেকিংপয়েন্টগুলি সেট করে স্বয়ংক্রিয় করতে পারেন (আবার উত্স কোড বিশ্লেষণ ব্যবহার করে, আপনি ast.Assert
পরীক্ষার একটি এএসটিতে নোডের জন্য তুচ্ছভাবে লাইন নম্বরগুলি বের করতে পারেন ), দৃ test়তম পরীক্ষার সম্পাদন করুন ডিবাগার স্ক্রিপ্টযুক্ত কমান্ডগুলি ব্যবহার করে, এবং jump
দৃ itself়তা বাদ দিতে কমান্ডটি ব্যবহার করুন । আপনাকে একটি ট্রেড অফ করতে হবে; একটি ডিবাগারের অধীনে সমস্ত পরীক্ষা চালান (যা দোভাষী প্রত্যেক বিবৃতিতে একটি ট্রেস ফাংশন কল করতে হয় তাই ধীর হয়) বা কেবল ব্যর্থ পরীক্ষায় এটি প্রয়োগ করুন এবং স্ক্র্যাচ থেকে সেই পরীক্ষাগুলি পুনরায় চালনার জন্য মূল্য প্রদান করুন pay
এই ধরনের একটি প্লাগইন তৈরি করতে অনেক কাজ হবে, আমি এখানে একটি উদাহরণ লিখব না, আংশিক কারণ এটি কোনওভাবেই কোনও জবাবের সাথে খাপ খায় না, এবং আংশিক কারণ এটি আমার পক্ষে সময়টির পক্ষে উপযুক্ত মনে হয় না । আমি সবেমাত্র ডিবাগারটি খুলি এবং নিজেই লাফিয়ে উঠতাম। একটি ব্যর্থতার জোড় পরীক্ষা নিজেই বা কোড-আন্ডার-টেস্টের মধ্যে একটি বাগ নির্দেশ করে, যাতে আপনি কেবল সমস্যাটি ডিবাগিংয়ে ফোকাস করতে পারেন।