{"id":28445,"date":"2026-08-28T18:32:45","date_gmt":"2026-08-28T18:32:45","guid":{"rendered":"https:\/\/umang.pk\/2026\/08\/28\/%d9%81%d9%84%d9%b9%d8%b1-%d8%a7%db%8c%d9%be%d8%b3-%da%a9%db%8c-%d8%ac%d8%a7%d9%86%da%86-%da%a9%db%8c%d8%b3%db%92-%da%a9%d8%b1%db%8c%da%ba-%db%8c%d9%88%d9%86%d9%b9%d8%8c-%d9%88%db%8c%d8%ac%db%8c%d9%b9\/"},"modified":"2026-08-28T18:32:45","modified_gmt":"2026-08-28T18:32:45","slug":"%d9%81%d9%84%d9%b9%d8%b1-%d8%a7%db%8c%d9%be%d8%b3-%da%a9%db%8c-%d8%ac%d8%a7%d9%86%da%86-%da%a9%db%8c%d8%b3%db%92-%da%a9%d8%b1%db%8c%da%ba-%db%8c%d9%88%d9%86%d9%b9%d8%8c-%d9%88%db%8c%d8%ac%db%8c%d9%b9","status":"publish","type":"post","link":"https:\/\/umang.pk\/ur\/2026\/08\/28\/%d9%81%d9%84%d9%b9%d8%b1-%d8%a7%db%8c%d9%be%d8%b3-%da%a9%db%8c-%d8%ac%d8%a7%d9%86%da%86-%da%a9%db%8c%d8%b3%db%92-%da%a9%d8%b1%db%8c%da%ba-%db%8c%d9%88%d9%86%d9%b9%d8%8c-%d9%88%db%8c%d8%ac%db%8c%d9%b9\/","title":{"rendered":"\u0641\u0644\u0679\u0631 \u0627\u06cc\u067e\u0633 \u06a9\u06cc \u062c\u0627\u0646\u0686 \u06a9\u06cc\u0633\u06d2 \u06a9\u0631\u06cc\u06ba: \u06cc\u0648\u0646\u0679\u060c \u0648\u06cc\u062c\u06cc\u0679\u060c \u06af\u0648\u0644\u0688\u0646\u060c \u0627\u0648\u0631 \u0627\u0646\u0679\u06cc\u06af\u0631\u06cc\u0634\u0646 \u0679\u06cc\u0633\u0679\u0646\u06af \u06a9\u06cc \u0648\u0636\u0627\u062d\u062a"},"content":{"rendered":"\n<div id=\"\">\n<p>\u067e\u06c1\u0644\u06cc \u0628\u0627\u0631\u060c \u0645\u062c\u06be \u0633\u06d2 \u0633\u0648\u0627\u0644 \u067e\u0648\u0686\u06be\u0627 \u06af\u06cc\u0627\u060c &quot;\u0679\u06cc\u0633\u0679\u0646\u06af \u06a9\u0627 \u062f\u0627\u0626\u0631\u06c1 \u06a9\u06cc\u0627 \u06c1\u06d2\u061f&#8221; \u0645\u062c\u06be\u06d2 \u062a\u06a9\u0646\u06cc\u06a9\u06cc \u0627\u0646\u0679\u0631\u0648\u06cc\u0648 \u0645\u06cc\u06ba \u0627\u0686\u06be\u06d2 \u062c\u0648\u0627\u0628 \u0646\u06c1\u06cc\u06ba \u0645\u0644\u06d2\u06d4<\/p>\n<p>\u062a\u0628 \u062a\u06a9\u060c \u0645\u06cc\u06ba \u0646\u06d2 \u0686\u0646\u062f \u062d\u0642\u06cc\u0642\u06cc \u0641\u0644\u0679\u0631 \u0627\u06cc\u067e\u0633 \u062c\u0627\u0631\u06cc \u06a9\u0631 \u062f\u06cc \u062a\u06be\u06cc\u06ba\u06d4 \u0648\u06c1 \u06a9\u0627\u0645 \u06a9\u0631 \u0631\u06c1\u06d2 \u062a\u06be\u06d2 \u0627\u0648\u0631 \u0635\u0627\u0631\u0641 \u0627\u0646\u06c1\u06cc\u06ba \u0627\u0633\u062a\u0639\u0645\u0627\u0644 \u06a9\u0631 \u0631\u06c1\u06d2 \u062a\u06be\u06d2\u06d4 \u0644\u06cc\u06a9\u0646 \u0645\u06cc\u0631\u06d2 \u0679\u06cc\u0633\u0679\u060c \u0627\u06af\u0631 \u0622\u067e \u0627\u0646\u06c1\u06cc\u06ba \u06a9\u06c1\u06c1 \u0633\u06a9\u062a\u06d2 \u06c1\u06cc\u06ba\u060c \u062a\u0648 \u0642\u06cc\u0645\u062a\u0648\u06ba \u06a9\u0627 \u062a\u0639\u06cc\u0646 \u06a9\u0631\u0646\u06d2 \u06a9\u06cc \u0641\u0639\u0627\u0644\u06cc\u062a \u06a9\u06d2 \u0644\u06cc\u06d2 \u0635\u0631\u0641 \u0686\u0646\u062f \u06cc\u0648\u0646\u0679 \u0679\u06cc\u0633\u0679 \u062a\u06be\u06d2 \u0627\u0648\u0631 \u06a9\u0686\u06be \u0646\u06c1\u06cc\u06ba\u06d4<\/p>\n<p>\u06a9\u0686\u06be \u0645\u06c1\u06cc\u0646\u0648\u06ba \u0628\u0639\u062f \u0645\u06cc\u06ba \u0646\u06d2 \u06a9\u0627\u0645 \u06a9\u06cc \u062a\u06a9\u0645\u06cc\u0644 \u06a9\u06d2 \u0628\u06c1\u0627\u0624 (\u0627\u06cc\u06a9 \u062a\u0628\u062f\u06cc\u0644\u06cc \u062c\u0648 \u06a9\u06c1 \u0641\u0631\u0642 \u0645\u06cc\u06ba \u0645\u06a9\u0645\u0644 \u0637\u0648\u0631 \u067e\u0631 \u0645\u062d\u0641\u0648\u0638 \u0644\u06af \u0631\u06c1\u06cc \u062a\u06be\u06cc) \u06a9\u0648 \u0631\u06cc \u0641\u06cc\u06a9\u0679\u0631 \u06a9\u06cc\u0627 \u0627\u0648\u0631 \u0627\u06cc\u06a9 \u0686\u06cc\u0632 \u06a9\u0648 \u062a\u0648\u0691 \u062f\u06cc\u0627 \u062c\u0633 \u06a9\u0627 \u0645\u06cc\u0631\u06d2 \u0635\u0627\u0631\u0641\u06cc\u0646 \u06a9\u0648 \u0627\u0635\u0644 \u062e\u06cc\u0627\u0644 \u062a\u06be\u0627\u06d4 \u06a9\u0633\u06cc \u06a9\u0627\u0645 \u06a9\u0648 \u0645\u06a9\u0645\u0644 \u06a9\u06d2 \u0628\u0637\u0648\u0631 \u0646\u0634\u0627\u0646 \u0632\u062f \u06a9\u0631\u0646\u06d2 \u0633\u06d2 \u0627\u0633\u06d2 \u063a\u0644\u0637 \u0641\u06c1\u0631\u0633\u062a \u0633\u06d2 \u06c1\u0679\u0627 \u062f\u06cc\u0627 \u06af\u06cc\u0627\u06d4 \u06a9\u0648\u0626\u06cc \u06a9\u0631\u06cc\u0634 \u0646\u06c1\u06cc\u06ba \u06c1\u0648\u0627 \u0627\u0648\u0631 \u06a9\u0648\u0626\u06cc \u062e\u0631\u0627\u0628\u06cc\u0627\u06ba \u0644\u0627\u06af \u0627\u0646 \u0646\u06c1\u06cc\u06ba \u06c1\u0648\u0626\u06cc\u06ba\u06d4 \u0635\u0627\u0631\u0641\u06cc\u0646 \u0646\u06d2 \u062e\u0627\u0645\u0648\u0634\u06cc \u0633\u06d2 \u0627\u06cc\u067e \u067e\u0631 \u0627\u0639\u062a\u0645\u0627\u062f \u06a9\u0631\u0646\u0627 \u0686\u06be\u0648\u0691 \u062f\u06cc\u0627 \u06c1\u06d2\u06d4 \u0627\u0648\u0631 \u0645\u06cc\u06ba \u0646\u06d2 \u0627\u0633 \u06a9\u06d2 \u0628\u0627\u0631\u06d2 \u0645\u06cc\u06ba \u0627\u06cc\u06a9 \u062f\u0648\u0633\u062a \u0633\u06d2 \u0628\u0627\u062a \u06a9\u0631\u06a9\u06d2 \u0645\u0639\u0644\u0648\u0645 \u06a9\u06cc\u0627 \u062c\u0648 \u0628\u06cc\u0679\u0627 \u0679\u06cc\u0633\u0679\u0631 \u062a\u06be\u0627\u06d4<\/p>\n<p>\u06cc\u06c1 \u062f\u0631\u0627\u0635\u0644 \u0648\u06c1 \u0628\u06af \u06c1\u06d2 \u062c\u0633 \u06a9\u06d2 \u0644\u06cc\u06d2 \u0679\u06cc\u0633\u0679\u0646\u06af \u06c1\u06d2\u06d4 \u06cc\u06c1 \u062d\u0627\u062f\u062b\u06c1 \u0646\u06c1\u06cc\u06ba \u06c1\u06d2 \u06a9\u06cc\u0648\u0646\u06a9\u06c1 \u062d\u0627\u062f\u062b\u06d2 \u06a9\u06cc \u0627\u0637\u0644\u0627\u0639 \u062f\u06cc \u06af\u0626\u06cc \u062a\u06be\u06cc\u06d4 \u0627\u06cc\u06a9 \u067e\u0631\u0633\u06a9\u0648\u0646 \u0631\u062c\u0639\u062a \u062c\u0648 \u0635\u0627\u0641 \u0637\u0648\u0631 \u067e\u0631 \u0641\u0631\u0627\u06c1\u0645 \u06a9\u0631\u062a\u06cc \u06c1\u06d2 \u0627\u0648\u0631 \u0627\u0639\u062a\u0645\u0627\u062f \u06a9\u0648 \u062a\u0648\u0691\u062a\u06cc \u06c1\u06d2 \u0648\u06c1 \u0627\u06cc\u0633\u06cc \u0686\u06cc\u0632 \u06c1\u06d2 \u062c\u0633\u06d2 \u0622\u067e \u0635\u0631\u0641 \u0627\u0633 \u0635\u0648\u0631\u062a \u0645\u06cc\u06ba \u067e\u06a9\u0691 \u0633\u06a9\u062a\u06d2 \u06c1\u06cc\u06ba \u062c\u0628 \u06a9\u0686\u06be \u062f\u06cc\u06a9\u06be \u0631\u06c1\u0627 \u06c1\u0648\u06d4<\/p>\n<p>\u062a\u0628 \u0633\u06d2\u060c \u06c1\u0645 \u0646\u06d2 \u0645\u0632\u06cc\u062f \u0627\u06cc\u067e\u0633 \u062c\u0627\u0631\u06cc \u06a9\u06cc \u06c1\u06cc\u06ba \u0627\u0648\u0631 \u0627\u0628 \u062c\u0627\u0646 \u0628\u0648\u062c\u06be \u06a9\u0631 \u0627\u0646 \u06a9\u06cc \u062c\u0627\u0646\u0686 \u06a9\u06cc \u06c1\u06d2\u06d4 \u0633\u0628 \u06a9\u0686\u06be \u0646\u06c1\u06cc\u06ba\u060c \u0644\u06cc\u06a9\u0646 \u0648\u06c1 \u062c\u0648 \u0627\u0635\u0644 \u0645\u06cc\u06ba \u0645\u062c\u06be\u06d2 \u0646\u0627\u0631\u0627\u0636 \u06a9\u0631\u062a\u06d2 \u06c1\u06cc\u06ba\u06d4<\/p>\n<p>\u06cc\u06c1 \u0645\u0636\u0645\u0648\u0646 \u0641\u0644\u0679\u0631 \u06a9\u06d2 \u0630\u0631\u06cc\u0639\u06d2 \u0641\u0631\u0627\u06c1\u0645 \u06a9\u0631\u062f\u06c1 \u0686\u0627\u0631 \u0642\u0633\u0645 \u06a9\u06d2 \u0679\u06cc\u0633\u0679\u0648\u06ba \u06a9\u0627 \u0627\u062d\u0627\u0637\u06c1 \u06a9\u0631\u062a\u0627 \u06c1\u06d2: \u06cc\u0648\u0646\u0679\u060c \u0648\u06cc\u062c\u06cc\u0679\u060c \u0633\u0646\u06c1\u0631\u06cc\u060c \u0627\u0648\u0631 \u0627\u0646\u0636\u0645\u0627\u0645\u06d4 \u0679\u06cc\u0633\u0679 \u0627\u06cc\u06a9 \u062d\u0642\u06cc\u0642\u06cc \u062f\u0646\u06cc\u0627 \u06a9\u06cc \u062e\u0635\u0648\u0635\u06cc\u062a \u06a9\u06d2 \u0627\u0631\u062f \u06af\u0631\u062f \u0628\u0646\u0627\u06cc\u0627 \u06af\u06cc\u0627 \u06c1\u06d2 \u0627\u0648\u0631 \u0686\u0627\u0631\u0648\u06ba \u0633\u0637\u062d\u0648\u06ba \u067e\u0631 \u0679\u06cc\u0633\u0679 \u06a9\u06cc\u0627 \u062c\u0627\u062a\u0627 \u06c1\u06d2\u06d4 \u0686\u0627\u0631 \u0645\u0646\u0642\u0637\u0639 \u0679\u06a9\u0691\u0648\u06ba \u06a9\u0648 \u067e\u0691\u06be\u0646\u06d2 \u0646\u06d2 \u0645\u062c\u06be\u06d2 \u06cc\u06c1 \u0646\u06c1\u06cc\u06ba \u0633\u06a9\u06be\u0627\u06cc\u0627 \u06a9\u06c1 \u0627\u0646 \u062a\u06c1\u0648\u06ba \u06a9\u0648 \u0627\u06cc\u06a9 \u0633\u0627\u062a\u06be \u06a9\u06cc\u0633\u06d2 \u0641\u0679 \u06c1\u0648\u0646\u0627 \u0686\u0627\u06c1\u0626\u06d2\u060c \u0644\u06c1\u0630\u0627 \u0645\u06cc\u06ba \u0627\u0633\u06d2 \u0627\u0633 \u0637\u0631\u062d \u06a9\u0631\u0646\u06d2 \u062c\u0627 \u0631\u06c1\u0627 \u06c1\u0648\u06ba\u06d4 \u0627\u0646 \u0633\u0628 \u06a9\u0648 \u0627\u06cc\u06a9 \u06c1\u06cc \u062e\u0635\u0648\u0635\u06cc\u0627\u062a \u06a9\u06d2 \u062e\u0644\u0627\u0641 \u0633\u062c\u0627 \u06c1\u0648\u0627 \u062f\u06cc\u06a9\u06be \u06a9\u0631 \u0622\u062e\u0631 \u06a9\u0627\u0631 \u0627\u0633 \u067e\u0631 \u06a9\u0644\u06a9 \u06c1\u0648\u0627\u06d4<\/p>\n<h2 id=\"heading-table-of-contents\">\u0627\u0646\u0688\u06cc\u06a9\u0633<\/h2>\n<h3 id=\"heading-prerequisites\">\u0634\u0631\u0637\u06cc\u06ba<\/h3>\n<p>\u0627\u0633 \u0679\u06cc\u0648\u0679\u0648\u0631\u06cc\u0644 \u06a9\u06d2 \u0633\u0627\u062a\u06be \u0622\u06af\u06d2 \u0628\u0691\u06be\u0646\u06d2 \u0633\u06d2 \u067e\u06c1\u0644\u06d2\u060c \u0622\u067e \u06a9\u0648 \u062f\u0631\u062c \u0630\u06cc\u0644 \u0633\u06d2 \u0648\u0627\u0642\u0641 \u06c1\u0648\u0646\u0627 \u0686\u0627\u06c1\u06cc\u06d2:<\/p>\n<ul>\n<li>\n<p><strong>\u0628\u0646\u06cc\u0627\u062f\u06cc \u0688\u0627\u0631\u0679 \u0627\u0648\u0631 \u0641\u0644\u0679\u0631 \u0646\u062d\u0648<\/strong>: \u0628\u0644\u0688\u0646\u06af \u06a9\u0644\u0627\u0633\u0632\u060c async\/await \u0627\u0648\u0631 \u0633\u0627\u062f\u06c1 \u0648\u06cc\u062c\u0679\u0633\u06d4 \u06cc\u06c1 \u0634\u0631\u0648\u0639 \u0633\u06d2 \u0641\u0644\u0679\u0631 \u0679\u06cc\u0648\u0679\u0648\u0631\u06cc\u0644 \u0646\u06c1\u06cc\u06ba \u06c1\u06d2 \u0627\u0648\u0631 \u0641\u0631\u0636 \u06a9\u0631\u062a\u0627 \u06c1\u06d2 \u06a9\u06c1 \u0622\u067e \u067e\u06c1\u0644\u06d2 \u06c1\u06cc \u0627\u0633\u06a9\u0631\u06cc\u0646\u06cc\u06ba \u0628\u0646\u0627 \u0633\u06a9\u062a\u06d2 \u06c1\u06cc\u06ba\u06d4 \u0634\u0627\u06cc\u062f \u0627\u0646\u06c1\u0648\u06ba \u0646\u06d2 \u0627\u0628\u06be\u06cc \u062a\u06a9 \u0627\u0633 \u06a9\u0627 \u0635\u062d\u06cc\u062d \u062a\u062c\u0631\u0628\u06c1 \u0646\u06c1\u06cc\u06ba \u06a9\u06cc\u0627 \u06c1\u06d2\u06d4<\/p>\n<\/li>\n<li>\n<p><strong>\u0641\u0631\u0627\u06c1\u0645 \u06a9\u0646\u0646\u062f\u06c1\/\u062a\u0628\u062f\u06cc\u0644 \u0646\u0648\u0679\u06cc\u0641\u0627\u0626\u0631 \u067e\u06cc\u0679\u0631\u0646<\/strong> \u06cc\u0627 \u06a9\u0686\u06be \u0627\u06cc\u0633\u0627 \u06c1\u06cc (\u0631\u06cc\u0648\u0631 \u067e\u0648\u0688\u060c \u0628\u0644\u0627\u06a9\u060c \u0648\u063a\u06cc\u0631\u06c1): <code>TaskNotifier<\/code> \u062a\u0648\u0633\u06cc\u0639 <code>ChangeNotifier<\/code>\u0627\u0648\u0631 \u0645\u062b\u0627\u0644\u0648\u06ba \u0633\u06d2 \u0627\u0646\u062f\u0627\u0632\u06c1 \u06c1\u0648\u062a\u0627 \u06c1\u06d2 \u06a9\u06c1 \u0622\u067e \u0631\u06cc\u0627\u0633\u062a\u06cc \u0627\u0646\u062a\u0638\u0627\u0645 \u06a9\u06d2 \u0627\u0633 \u0627\u0646\u062f\u0627\u0632 \u0633\u06d2 \u0648\u0627\u0642\u0641 \u06c1\u06cc\u06ba\u060c \u0686\u0627\u06c1\u06d2 \u0622\u067e \u06a9\u06cc \u0627\u06cc\u067e \u06a9\u0648\u0626\u06cc \u0645\u062e\u062a\u0644\u0641 \u0648\u0631\u0698\u0646 \u0627\u0633\u062a\u0639\u0645\u0627\u0644 \u06a9\u0631\u06d2\u06d4<\/p>\n<\/li>\n<\/ul>\n<p>\u0622\u067e \u06a9\u0648 \u062f\u0631\u062c \u0630\u06cc\u0644 \u06a9\u0648 \u0628\u06be\u06cc \u0627\u0646\u0633\u0679\u0627\u0644 \u0627\u0648\u0631 \u0633\u06cc\u0679 \u0627\u067e \u06a9\u0631\u0646\u0627 \u06c1\u0648\u06af\u0627:<\/p>\n<ul>\n<li>\n<p><strong>\u0641\u0644\u0679\u0631 SDK<\/strong> (\u06cc\u06c1 \u062a\u0627\u0632\u06c1 \u062a\u0631\u06cc\u0646 \u0645\u0633\u062a\u062d\u06a9\u0645 \u0648\u0631\u0698\u0646 \u06c1\u06d2\u06d4 \u0645\u062b\u0627\u0644\u06cc\u06ba \u062c\u062f\u06cc\u062f \u062a\u0631\u06cc\u0646 \u0679\u06cc\u06a9\u0646\u0627\u0644\u0648\u062c\u06cc \u067e\u0631 \u0645\u0646\u062d\u0635\u0631 \u0646\u06c1\u06cc\u06ba \u06c1\u06cc\u06ba\u06d4)<\/p>\n<\/li>\n<li>\n<p><strong>\u0641\u0644\u0679\u0631\/\u0688\u0627\u0631\u0679 \u06a9\u0648 \u0633\u067e\u0648\u0631\u0679 \u06a9\u0631\u0646\u06d2 \u0648\u0627\u0644\u0627 \u0627\u06cc\u0688\u06cc\u0679\u0631<\/strong> (VS \u06a9\u0648\u0688 \u06cc\u0627 \u0627\u06cc\u0646\u0688\u0631\u0627\u0626\u06cc\u0688 \u0627\u0633\u0679\u0648\u0688\u06cc\u0648 \u062f\u0648\u0646\u0648\u06ba \u0627\u0686\u06be\u06cc \u0637\u0631\u062d \u06a9\u0627\u0645 \u06a9\u0631\u062a\u06d2 \u06c1\u06cc\u06ba)<\/p>\n<\/li>\n<li>\n<p><strong>\u0688\u06cc\u0648\u0627\u0626\u0633 \u06cc\u0627 \u0627\u06cc\u0645\u0648\u0644\u06cc\u0679\u0631<\/strong> \u062e\u0627\u0635 \u0637\u0648\u0631 \u067e\u0631 \u0627\u0646\u0679\u06cc\u06af\u0631\u06cc\u0634\u0646 \u0679\u06cc\u0633\u0679\u0646\u06af \u0633\u06cc\u06a9\u0634\u0646 \u06a9\u06d2 \u0644\u06cc\u06d2\u06d4 \u0627\u06cc\u06a9 iOS \u0633\u0645\u06cc\u0644\u06cc\u0679\u0631 \u06cc\u0627 \u0627\u06cc\u0646\u0688\u0631\u0627\u0626\u06cc\u0688 \u0627\u06cc\u0645\u0648\u0644\u06cc\u0679\u0631 \u06a9\u0627\u0641\u06cc \u06c1\u0648\u06af\u0627\u06d4 \u062c\u0633\u0645\u0627\u0646\u06cc \u06c1\u0627\u0631\u0688 \u0648\u06cc\u0626\u0631 \u06a9\u06cc \u0636\u0631\u0648\u0631\u062a \u0646\u06c1\u06cc\u06ba \u06c1\u06d2\u06d4<\/p>\n<\/li>\n<li>\n<p><strong>\u0627\u06af\u0644\u0627 \u062a\u0631\u0642\u06cc \u0627\u0646\u062d\u0635\u0627\u0631<\/strong>\u062c\u0628 \u0628\u06be\u06cc \u06cc\u06c1 \u0633\u0627\u0645\u0646\u06d2 \u0622\u062a\u0627 \u06c1\u06d2 \u0627\u0633\u06d2 \u0646\u0645\u0627\u06cc\u0627\u06ba \u06a9\u06cc\u0627 \u062c\u0627\u062a\u0627 \u06c1\u06d2\u060c \u0644\u06cc\u06a9\u0646 \u0627\u0633 \u06a9\u0627 \u06c1\u0648\u0646\u0627 \u0642\u0627\u0628\u0644 \u0642\u062f\u0631 \u06c1\u06d2\u06d4<\/p>\n<\/li>\n<\/ul>\n<pre><code class=\"language-yaml\">  dev_dependencies:\n    flutter_test:\n      sdk: flutter\n    integration_test:\n      sdk: flutter\n    mocktail: ^1.0.4\n    golden_toolkit: ^0.15.0\n<\/code><\/pre>\n<p>\u0627\u06af\u0631 \u0645\u06cc\u06ba \u062f\u0648\u0691 \u0633\u06a9\u062a\u0627 <code>flutter test<\/code> \u06cc\u06c1 \u0627\u06cc\u06a9 \u062e\u0627\u0644\u06cc \u067e\u0631\u0648\u062c\u06cc\u06a9\u0679 \u0645\u06cc\u06ba \u0635\u0627\u0641 \u0637\u0648\u0631 \u067e\u0631 \u062e\u062a\u0645 \u06c1\u0648\u062a\u0627 \u06c1\u06d2\u060c \u062c\u0627\u0646\u06d2 \u06a9\u06d2 \u0644\u06cc\u06d2 \u062a\u06cc\u0627\u0631 \u06c1\u06d2\u06d4<\/p>\n<h2 id=\"heading-why-four-kinds-of-tests-not-just-tests\">\u06c1\u0645\u06cc\u06ba \u0686\u0627\u0631 \u0642\u0633\u0645 \u06a9\u06d2 \u0679\u06cc\u0633\u0679\u0648\u06ba \u06a9\u06cc \u0636\u0631\u0648\u0631\u062a \u06a9\u06cc\u0648\u06ba \u06c1\u06d2 \u0646\u06c1 \u06a9\u06c1 \u0635\u0631\u0641 &quot;\u0679\u06cc\u0633\u0679&#8221; \u06a9\u06cc\u061f<\/h2>\n<p>\u062a\u0645\u0627\u0645 \u0627\u0628\u062a\u062f\u0627\u0626\u06cc \u0641\u0644\u0679\u0631 \u0679\u06cc\u0633\u0679\u0646\u06af \u0679\u06cc\u0648\u0679\u0648\u0631\u06cc\u0644\u0632 \u062c\u0646 \u06a9\u0648 \u0645\u06cc\u06ba \u0646\u06d2 &quot;\u0679\u06cc\u0633\u0679\u0646\u06af&#8221; \u06a9\u0648 \u0627\u06cc\u06a9 \u0633\u0631\u06af\u0631\u0645\u06cc \u06a9\u06d2 \u0637\u0648\u0631 \u067e\u0631 \u067e\u0691\u06be\u0627 \u06c1\u06d2\u06d4 \u06cc\u06c1 \u0633\u0686 \u0646\u06c1\u06cc\u06ba \u06c1\u06d2\u06d4 \u0686\u0627\u0631 \u0642\u0633\u0645\u06cc\u06ba \u0686\u0627\u0631 \u0645\u062e\u062a\u0644\u0641 \u0633\u0648\u0627\u0644\u0648\u06ba \u06a9\u06d2 \u062c\u0648\u0627\u0628 \u062f\u06cc\u062a\u06cc \u06c1\u06cc\u06ba\u060c \u0627\u0648\u0631 \u062c\u0648 \u0686\u06cc\u0632 \u062c\u0627\u0646\u0686 \u06a9\u0648 \u0627\u062a\u0646\u0627 \u0627\u0644\u062c\u06be\u0627 \u062f\u06cc\u062a\u06cc \u06c1\u06d2 \u0648\u06c1 \u06cc\u06c1 \u06c1\u06d2 \u06a9\u06c1 \u0622\u067e \u0627\u0633\u06d2 \u06a9\u0633 \u0637\u0631\u062d \u06a9\u0631\u062a\u06d2 \u06c1\u06cc\u06ba \u0627\u0633 \u067e\u0631 \u0645\u0646\u062d\u0635\u0631 \u06c1\u06d2 \u06a9\u06c1 \u06cc\u06c1 \u062d\u062f \u0633\u06d2 \u0632\u06cc\u0627\u062f\u06c1 \u06cc\u0627 \u0648\u0642\u062a \u06a9\u0627 \u0636\u06cc\u0627\u0639 \u06a9\u06cc\u0648\u06ba \u0645\u062d\u0633\u0648\u0633 \u06c1\u0648\u062a\u0627 \u06c1\u06d2\u06d4<\/p>\n<p><strong>\u06cc\u0648\u0646\u0679 \u0679\u06cc\u0633\u0679\u0646\u06af<\/strong> \u062c\u0648\u0627\u0628: \u06a9\u06cc\u0627 \u0645\u0646\u0637\u0642 \u06a9\u0627 \u06cc\u06c1 \u062e\u0627\u0635 \u0679\u06a9\u0691\u0627 \u062f\u06cc\u06d2 \u06af\u0626\u06d2 \u0627\u0646 \u067e\u0679 \u06a9\u06d2 \u0644\u06cc\u06d2 \u0635\u062d\u06cc\u062d \u0622\u0624\u0679 \u067e\u0679 \u067e\u06cc\u062f\u0627 \u06a9\u0631\u062a\u0627 \u06c1\u06d2\u061f \u06a9\u0648\u0626\u06cc \u0648\u06cc\u062c\u0679\u060c \u0631\u06cc\u0646\u0688\u0631\u0646\u06af \u06cc\u0627 \u0646\u0642\u0644\u06cc \u0622\u0644\u0627\u062a \u0646\u06c1\u06cc\u06ba \u06c1\u06cc\u06ba\u06d4 \u0622\u067e \u06a9\u0648 \u0635\u0631\u0641 \u0627\u06cc\u06a9 \u0641\u0646\u06a9\u0634\u0646 \u06cc\u0627 \u06a9\u0644\u0627\u0633\u060c \u0627\u0648\u0631 \u0627\u06cc\u06a9 \u062f\u0639\u0648\u06cc\u0670 \u06a9\u06cc \u0636\u0631\u0648\u0631\u062a \u06c1\u06d2\u06d4 \u06cc\u06c1 \u0645\u0644\u06cc \u0633\u06cc\u06a9\u0646\u0688 \u0645\u06cc\u06ba \u0686\u0644\u062a\u0627 \u06c1\u06d2\u060c \u0627\u06af\u0631 \u0636\u0631\u0648\u0631\u06cc \u06c1\u0648 \u062a\u0648 \u06c1\u0632\u0627\u0631\u0648\u06ba\u06d4<\/p>\n<p><strong>\u0648\u06cc\u062c\u06cc\u0679 \u0679\u06cc\u0633\u0679<\/strong> \u062c\u0648\u0627\u0628: \u06a9\u06cc\u0627 \u06cc\u06c1 \u0648\u06cc\u062c\u06cc\u0679 \u06a9\u0686\u06be \u0631\u06cc\u0627\u0633\u062a\u0648\u06ba \u0645\u06cc\u06ba \u0635\u062d\u06cc\u062d \u0637\u0631\u06cc\u0642\u06d2 \u0633\u06d2 \u0631\u06cc\u0646\u0688\u0631 \u0627\u0648\u0631 \u06a9\u0627\u0645 \u06a9\u0631\u062a\u0627 \u06c1\u06d2\u061f \u06cc\u06c1 \u0627\u0635\u0644\u06cc \u0622\u0644\u0627\u062a \u06cc\u0627 \u0627\u0635\u0644\u06cc \u067e\u06a9\u0633\u0644\u0632 \u06a9\u06d2 \u0628\u063a\u06cc\u0631 \u0646\u0642\u0644\u06cc \u0645\u0627\u062d\u0648\u0644 \u0645\u06cc\u06ba \u0686\u0644\u062a\u0627 \u06c1\u06d2\u06d4 \u0627\u0648\u0631 \u062c\u0628 \u0628\u06be\u06cc \u0622\u067e \u0628\u0686\u062a \u06a9\u0631\u062a\u06d2 \u06c1\u06cc\u06ba \u062a\u0648 \u0686\u0644\u0627\u0646\u06d2 \u06a9\u06d2 \u0644\u06cc\u06d2 \u06cc\u06c1 \u06a9\u0627\u0641\u06cc \u062a\u06cc\u0632 \u06c1\u06d2\u060c \u0644\u06cc\u06a9\u0646 \u067e\u06a9\u0691\u0646\u06d2 \u06a9\u06d2 \u0644\u06cc\u06d2 \u06a9\u0627\u0641\u06cc \u062d\u0642\u06cc\u0642\u062a \u067e\u0633\u0646\u062f\u0627\u0646\u06c1 \u06c1\u06d2 &quot;\u0627\u06af\u0631 \u062f\u0631\u062e\u0648\u0627\u0633\u062a \u0646\u0627\u06a9\u0627\u0645 \u06c1\u0648\u062c\u0627\u062a\u06cc \u06c1\u06d2\u060c \u062a\u0648 \u0622\u067e \u06a9\u0648 \u062f\u0648\u0628\u0627\u0631\u06c1 \u06a9\u0648\u0634\u0634 \u06a9\u0631\u0646\u06d2 \u06a9\u0627 \u0628\u0679\u0646 \u0646\u0638\u0631 \u0646\u06c1\u06cc\u06ba \u0622\u0626\u06d2 \u06af\u0627\u06d4&#8221;<\/p>\n<p><strong>\u0633\u0646\u06c1\u0631\u06cc \u0679\u06cc\u0633\u0679<\/strong> \u062c\u0648\u0627\u0628: \u06a9\u06cc\u0627 \u06cc\u06c1 \u0648\u06cc\u062c\u06cc\u0679 \u0627\u0628 \u0628\u06be\u06cc \u062f\u0633\u062a\u06cc\u0627\u0628 \u06c1\u06d2\u061f <em>\u062f\u06cc\u06a9\u06be\u0648<\/em> \u06a9\u06cc\u0627 \u06cc\u06c1 \u0648\u06c1\u06cc \u06c1\u06d2\u061f \u0631\u06cc\u0646\u0688\u0631 \u06a9\u0631\u062f\u06c1 \u0648\u06cc\u062c\u06cc\u0679 \u067e\u06a9\u0633\u0644 \u0628\u06c1 \u067e\u06a9\u0633\u0644 \u06a9\u0627 \u0627\u06cc\u06a9 \u0630\u062e\u06cc\u0631\u06c1 \u0634\u062f\u06c1 \u062d\u0648\u0627\u0644\u06c1 \u062a\u0635\u0648\u06cc\u0631 \u06a9\u06d2 \u0633\u0627\u062a\u06be \u0645\u0648\u0627\u0632\u0646\u06c1 \u06a9\u0631\u062a\u0627 \u06c1\u06d2\u06d4 \u06cc\u06c1 \u0686\u0627\u0631\u0648\u06ba \u0645\u06cc\u06ba \u0633\u06d2 \u0635\u0631\u0641 \u0627\u06cc\u06a9 \u06c1\u06d2 \u062c\u0648 &quot;\u067e\u06cc\u0688\u0646\u06af \u0627\u0628 \u063a\u0644\u0637 \u06c1\u06d2&#8221; \u06cc\u0627 &quot;\u0679\u06cc\u06a9\u0633\u0679 \u0627\u0648\u0648\u0631 \u0641\u0644\u0648&#8221; \u06a9\u0648 \u067e\u06a9\u0691 \u0633\u06a9\u062a\u0627 \u06c1\u06d2\u06d4 \u06cc\u06c1 \u0686\u06cc\u0632\u06cc\u06ba \u0627\u0646\u0633\u0627\u0646\u0648\u06ba \u06a9\u06d2 \u0644\u06cc\u06d2 \u0628\u0635\u0631\u06cc \u0637\u0648\u0631 \u067e\u0631 \u0638\u0627\u06c1\u0631 \u06c1\u06cc\u06ba \u0644\u06cc\u06a9\u0646 \u0627\u0646\u0633\u0627\u0646\u0648\u06ba \u06a9\u06d2 \u0644\u06cc\u06d2 \u067e\u0648\u0634\u06cc\u062f\u06c1 \u06c1\u06cc\u06ba\u06d4 <code>find.text()<\/code> \u062a\u0636\u0627\u062f<\/p>\n<p><strong>\u0627\u0646\u0636\u0645\u0627\u0645 \u06a9\u06cc \u062c\u0627\u0646\u0686<\/strong> \u062c\u0648\u0627\u0628: \u06a9\u06cc\u0627 \u062d\u0642\u06cc\u0642\u06cc \u0627\u06cc\u067e\u0633 \u062c\u0648 \u0627\u0635\u0644\u06cc \u06cc\u0627 \u0646\u0642\u0644\u06cc \u0622\u0644\u0627\u062a \u067e\u0631 \u0645\u0631\u062a\u0628 \u0627\u0648\u0631 \u0686\u0644\u062a\u06cc \u06c1\u06cc\u06ba \u062f\u0631\u0627\u0635\u0644 \u0622\u062e\u0631 \u0633\u06d2 \u0622\u062e\u0631 \u062a\u06a9 \u06a9\u0627\u0645 \u06a9\u0631\u062a\u06cc \u06c1\u06cc\u06ba\u061f \u06cc\u06c1 \u0633\u0633\u062a \u06c1\u06d2\u060c \u0646\u0633\u0628\u062a\u0627\u064b \u0645\u06c1\u0646\u06af\u0627 \u06c1\u06d2\u060c \u0627\u0648\u0631 \u0627\u0646 \u0686\u0627\u0631 \u0645\u06cc\u06ba \u0633\u06d2 \u0635\u0631\u0641 \u0627\u06cc\u06a9 \u06c1\u06d2 \u062c\u0648 \u0635\u0631\u0641 \u06a9\u0631\u0627\u0633 \u0644\u06cc\u0626\u0631 \u062a\u0639\u0627\u0645\u0644\u0627\u062a \u0645\u06cc\u06ba \u0645\u0648\u062c\u0648\u062f \u06a9\u06cc\u0691\u06d2 \u067e\u06a9\u0691 \u0633\u06a9\u062a\u0627 \u06c1\u06d2\u060c \u062c\u06cc\u0633\u06d2 \u06a9\u06c1 \u06a9\u0648\u0626\u06cc \u0627\u0633\u0679\u0648\u0631 \u063a\u0644\u0637 \u0642\u0633\u0645 \u06a9\u0648 \u0646\u0648\u0679\u06cc\u0641\u0627\u0626\u0631 \u06a9\u0648 \u0648\u0627\u067e\u0633 \u06a9\u0631\u062a\u0627 \u06c1\u06d2 \u062c\u0648 \u0628\u06c1\u0631\u062d\u0627\u0644 \u062f\u0631\u0633\u062a \u0637\u0631\u06cc\u0642\u06d2 \u0633\u06d2 \u067e\u06cc\u0634 \u06a9\u0631\u062a\u0627 \u06c1\u06d2\u06d4<\/p>\n<p>\u0686\u0627\u0631 \u0645\u06cc\u06ba \u0633\u06d2 \u06a9\u0648\u0626\u06cc \u0628\u06be\u06cc \u062f\u0648\u0633\u0631\u06d2 \u06a9\u06cc \u062c\u06af\u06c1 \u0646\u06c1\u06cc\u06ba \u0644\u06cc\u062a\u0627\u06d4 \u0642\u06cc\u0645\u062a\u0648\u06ba \u06a9\u06d2 \u06a9\u06cc\u0691\u06d2 \u06cc\u0648\u0646\u0679 \u0679\u06cc\u0633\u0679 \u0645\u06cc\u06ba \u06c1\u06cc\u06ba\u06d4 \u06af\u0645\u0634\u062f\u06c1 \u062e\u0631\u0627\u0628\u06cc \u06a9\u06cc \u0634\u0631\u0627\u0626\u0637 \u0648\u06cc\u062c\u06cc\u0679 \u0679\u06cc\u0633\u0679 \u0633\u06d2 \u062a\u0639\u0644\u0642 \u0631\u06a9\u06be\u062a\u06cc \u06c1\u06cc\u06ba\u06d4 \u0645\u0646\u062a\u0642\u0644 \u0634\u062f\u06c1 \u062a\u0631\u062a\u06cc\u0628 \u06af\u0648\u0644\u0688\u0646 \u0679\u06cc\u0633\u0679 \u06a9\u06d2 \u062a\u062d\u062a \u0622\u062a\u0627 \u06c1\u06d2\u06d4 \u0679\u0648\u0679\u06d2 \u06c1\u0648\u0626\u06d2 \u0627\u06cc\u0646\u0688 \u0679\u0648 \u0627\u06cc\u0646\u0688 \u0641\u0644\u0648\u0632 \u0627\u0646\u0636\u0645\u0627\u0645 \u0679\u06cc\u0633\u0679 \u0633\u06d2 \u062a\u0639\u0644\u0642 \u0631\u06a9\u06be\u062a\u06d2 \u06c1\u06cc\u06ba\u06d4 \u0686\u0627\u0631 \u0645\u06cc\u06ba \u0633\u06d2 \u0635\u0631\u0641 \u0627\u06cc\u06a9 \u06a9\u0648 \u0627\u0633\u062a\u0639\u0645\u0627\u0644 \u06a9\u0631\u0646\u06d2 \u06a9\u0627 \u0645\u0637\u0644\u0628 \u06c1\u06d2 \u06a9\u06c1 \u062a\u06cc\u0646 \u0642\u0633\u0645 \u06a9\u06d2 \u06a9\u06cc\u0679\u06af\u0631\u06cc\u0632 \u06a9\u0627 \u067e\u062a\u06c1 \u0646\u06c1 \u0686\u0644 \u0633\u06a9\u0627\u06d4<\/p>\n<h2 id=\"heading-the-feature-were-testing\">\u062e\u0635\u0648\u0635\u06cc\u0627\u062a \u06a9\u06cc \u062c\u0627\u0646\u0686 \u06a9\u06cc \u062c\u0627 \u0631\u06c1\u06cc \u06c1\u06d2\u06d4<\/h2>\n<p>\u0627\u0633 \u06a9\u0646\u06a9\u0631\u06cc\u0679 \u06a9\u0648 \u0628\u0631\u0642\u0631\u0627\u0631 \u0631\u06a9\u06be\u0646\u06d2 \u06a9\u06d2 \u0644\u06cc\u06d2\u060c \u062a\u0645\u0627\u0645 \u0633\u06cc\u06a9\u0634\u0646\u0632 \u0627\u06cc\u06a9 \u06c1\u06cc \u0641\u0639\u0627\u0644\u06cc\u062a \u06a9\u06d2 \u0627\u0631\u062f \u06af\u0631\u062f \u0628\u0646\u0627\u0626\u06d2 \u06af\u0626\u06d2 \u06c1\u06cc\u06ba: \u0627\u06cc\u06a9 \u0679\u0627\u0633\u06a9 \u0644\u0633\u0679 \u062c\u06c1\u0627\u06ba \u0635\u0627\u0631\u0641 \u06a9\u0627\u0645\u0648\u06ba \u06a9\u0648 \u0645\u06a9\u0645\u0644 \u06a9\u06d2 \u0637\u0648\u0631 \u067e\u0631 \u0646\u0634\u0627\u0646 \u0632\u062f \u06a9\u0631 \u0633\u06a9\u062a\u06d2 \u06c1\u06cc\u06ba\u060c \u062c\u0633 \u062a\u0639\u062f\u0627\u062f \u06a9\u06d2 \u0633\u0627\u062a\u06be \u0648\u06c1 \u0627\u06cc\u067e \u0628\u0627\u0631 \u0645\u06cc\u06ba \u0638\u0627\u06c1\u0631 \u06c1\u0648\u062a\u06d2 \u06c1\u06cc\u06ba\u06d4<\/p>\n<pre><code class=\"language-dart\">\/\/ lib\/task.dart\nclass Task {\n  const Task({required this.id, required this.title, this.isDone = false});\n\n  final String id;\n  final String title;\n  final bool isDone;\n\n  Task copyWith({bool? isDone}) =>\n      Task(id: id, title: title, isDone: isDone ?? this.isDone);\n}\n<\/code><\/pre>\n<pre><code class=\"language-dart\">\/\/ lib\/task_repository.dart\nabstract class TaskRepository {\n  Future<list>> fetchTasks();\n  Future<void> setTaskDone(String id, bool isDone);\n}\n<\/void><\/list><\/code><\/pre>\n<pre><code class=\"language-dart\">\/\/ lib\/task_logic.dart\n\n\/\/\/ The bug I actually shipped: this used to filter on the wrong\n\/\/\/ field when a task list contained tasks from more than one list,\n\/\/\/ silently completing a task in the wrong place. A single unit\n\/\/\/ test on this function would have caught it before it shipped.\nint countCompleted(List<task> tasks) =>\n    tasks.where(\n\nList<task> markDone(List<task> tasks, String id) => tasks\n    .map(\n    .toList();\n<\/task><\/task><\/task><\/code><\/pre>\n<pre><code class=\"language-dart\">\/\/ lib\/task_notifier.dart\nclass TaskNotifier extends ChangeNotifier {\n  TaskNotifier(this._repository);\n  final TaskRepository _repository;\n\n  List<task> _tasks = [];\n  bool isLoading = false;\n  String? error;\n\n  List<task> get tasks => _tasks;\n  int get completedCount => countCompleted(_tasks);\n\n  Future<void> load() async {\n    isLoading = true;\n    error = null;\n    notifyListeners();\n\n    try {\n      _tasks = await _repository.fetchTasks();\n    } catch (_) {\n      error=\"Failed to load tasks. Please try again.\";\n    }\n\n    isLoading = false;\n    notifyListeners();\n  }\n\n  Future<void> complete(String id) async {\n    final previous = _tasks;\n    _tasks = markDone(_tasks, id); \/\/ optimistic update\n    notifyListeners();\n\n    try {\n      await _repository.setTaskDone(id, true);\n    } catch (_) {\n      _tasks = previous; \/\/ roll back on failure\n      notifyListeners();\n    }\n  }\n}\n<\/void><\/void><\/task><\/task><\/code><\/pre>\n<pre><code class=\"language-dart\">\/\/ lib\/task_screen.dart\nclass TaskScreen extends StatefulWidget {\n  const TaskScreen({super.key, required this.notifier});\n  final TaskNotifier notifier;\n\n  @override\n  State<taskscreen> createState() => _TaskScreenState();\n}\n\nclass _TaskScreenState extends State<taskscreen> {\n  @override\n  void initState() {\n    super.initState();\n    widget.notifier.load();\n  }\n\n  @override\n  Widget build(BuildContext context) {\n    return AnimatedBuilder(\n      animation: widget.notifier,\n      builder: (context, _) {\n        final notifier = widget.notifier;\n\n        return Scaffold(\n          appBar: AppBar(title: Text('Tasks (${notifier.completedCount} done)')),\n          body: notifier.isLoading\n              ? const Center(child: CircularProgressIndicator())\n              : notifier.error != null\n                  ? Center(\n                      child: Column(\n                        mainAxisSize: MainAxisSize.min,\n                        children: [\n                          Text(notifier.error!),\n                          const SizedBox(height: 8),\n                          ElevatedButton(\n                            onPressed: notifier.load,\n                            child: const Text('Retry'),\n                          ),\n                        ],\n                      ),\n                    )\n                  : ListView(\n                      children: notifier.tasks\n                          .map((task) => CheckboxListTile(\n                                key: ValueKey(task.id),\n                                title: Text(task.title),\n                                value: task.isDone,\n                                onChanged: task.isDone\n                                    ? null\n                                    : (_) => notifier.complete(task.id),\n                              ))\n                          .toList(),\n                    ),\n        );\n      },\n    );\n  }\n}\n<\/taskscreen><\/taskscreen><\/code><\/pre>\n<p>\u06cc\u06c1 \u0645\u06a9\u0645\u0644 \u0641\u0639\u0627\u0644\u06cc\u062a \u06c1\u06d2\u06d4 \u0627\u0628 \u06c1\u0645 \u0627\u0633\u06d2 \u0686\u0627\u0631 \u0637\u0631\u06cc\u0642\u0648\u06ba \u0633\u06d2 \u062c\u0627\u0646\u0686\u062a\u06d2 \u06c1\u06cc\u06ba:<\/p>\n<h2 id=\"heading-unit-tests-business-logic-in-isolation\">\u06cc\u0648\u0646\u0679 \u0679\u06cc\u0633\u0679\u0646\u06af: \u0627\u0644\u06af \u062a\u06be\u0644\u06af \u06a9\u0627\u0631\u0648\u0628\u0627\u0631\u06cc \u0645\u0646\u0637\u0642<\/h2>\n<p><code>countCompleted<\/code>    \u0627\u0648\u0631 <code>markDone<\/code> \u06cc\u06c1 \u0627\u06cc\u06a9 \u0628\u0627\u0642\u0627\u0639\u062f\u06c1 \u0688\u0627\u0631\u0679 \u0641\u0646\u06a9\u0634\u0646 \u06c1\u06d2 \u062c\u0633 \u0645\u06cc\u06ba \u06a9\u0648\u0626\u06cc \u0641\u0644\u0679\u0631 \u0627\u0646\u062d\u0635\u0627\u0631 \u0646\u06c1\u06cc\u06ba \u06c1\u06d2\u06d4 \u0646\u06c1\u06cc\u06ba <code>BuildContext<\/code>\u06a9\u0648\u0626\u06cc \u0628\u06be\u06cc \u0686\u06cc\u0632 \u062c\u0633 \u06a9\u06cc \u0622\u067e \u06a9\u0648 \u0648\u06cc\u062c\u06cc\u0679 \u06cc\u0627 \u0679\u06cc\u0633\u0679 \u0631\u06af \u06a9\u06cc \u0636\u0631\u0648\u0631\u062a \u06c1\u0648\u06d4 \u06cc\u06c1 \u062c\u0627\u0646 \u0628\u0648\u062c\u06be \u06a9\u0631 \u06c1\u06d2\u06d4 \u0627\u0633 \u0627\u06c1\u0645 \u0645\u0646\u0637\u0642 \u06a9\u06d2 \u0644\u06cc\u06d2 \u0631\u06cc\u0646\u0688\u0631\u0646\u06af \u0627\u0646\u062c\u0646 \u06a9\u06cc \u062a\u0635\u062f\u06cc\u0642 \u06a9\u06cc \u0636\u0631\u0648\u0631\u062a \u0646\u06c1\u06cc\u06ba \u06c1\u06d2\u06d4<\/p>\n<pre><code class=\"language-dart\">\/\/ test\/task_logic_test.dart\nimport 'package:flutter_test\/flutter_test.dart';\nimport 'package:my_app\/task.dart';\nimport 'package:my_app\/task_logic.dart';\n\nvoid main() {\n  group('countCompleted', () {\n    test('returns 0 for an empty list', () {\n      expect(countCompleted([]), 0);\n    });\n\n    test('counts only tasks marked done', () {\n      final tasks = [\n        const Task(id: '1', title: 'A', isDone: true),\n        const Task(id: '2', title: 'B', isDone: false),\n        const Task(id: '3', title: 'C', isDone: true),\n      ];\n\n      expect(countCompleted(tasks), 2);\n    });\n  });\n\n  group('markDone', () {\n    test('marks only the task with the matching id', () {\n      final tasks = [\n        const Task(id: '1', title: 'A'),\n        const Task(id: '2', title: 'B'),\n      ];\n\n      final result = markDone(tasks, '2');\n\n      \/\/ The critical assertion \u2014 this is the exact bug I shipped.\n      \/\/ A naive implementation that filters on the wrong field\n      \/\/ would mark task '1' done instead, or both, and this\n      \/\/ test would fail immediately instead of surfacing in\n      \/\/ a user's bug report three weeks later.\n      expect(result.firstWhere(\n      expect(result.firstWhere(\n    });\n\n    test('returns an unchanged list if the id does not exist', () {\n      final tasks = [const Task(id: '1', title: 'A')];\n      final result = markDone(tasks, 'nonexistent');\n\n      expect(result.first.isDone, false);\n    });\n  });\n}\n<\/code><\/pre>\n<p>\u0627\u0633\u06d2 \u0627\u0633\u062a\u0639\u0645\u0627\u0644 \u06a9\u0631\u062a\u06d2 \u06c1\u0648\u0626\u06d2 \u0686\u0644\u0627\u0626\u06cc\u06ba:<\/p>\n<pre><code class=\"language-bash\">flutter test test\/task_logic_test.dart\n<\/code><\/pre>\n<p>\u06c1\u0631 \u0679\u06cc\u0633\u0679 \u0686\u0646\u062f \u0645\u0644\u06cc \u0633\u06cc\u06a9\u0646\u0688 \u0645\u06cc\u06ba \u0686\u0644\u062a\u0627 \u06c1\u06d2\u06d4 \u0627\u0646 \u0679\u06cc\u0633\u0679\u0648\u06ba \u06a9\u0648 \u0644\u06a9\u06be\u0646\u06d2 \u06a9\u0648 \u0686\u06be\u0648\u0691\u0646\u06d2 \u06a9\u06cc \u06a9\u0648\u0626\u06cc \u0648\u062c\u06c1 \u0646\u06c1\u06cc\u06ba \u06c1\u06d2\u06d4 \u06cc\u06c1 \u0627\u06cc\u06a9 \u067e\u0631\u062a \u06c1\u06d2 \u062c\u06c1\u0627\u06ba \u0646\u0627\u0642\u0635 \u0645\u0641\u0631\u0648\u0636\u0648\u06ba \u06a9\u0648 \u062e\u0648\u062f \u0628\u062e\u0648\u062f \u067e\u06cc\u062f\u0627\u0648\u0627\u0631 \u0645\u06cc\u06ba \u062f\u06be\u06a9\u06cc\u0644 \u062f\u06cc\u0627 \u062c\u0627\u062a\u0627 \u06c1\u06d2 \u06a9\u06cc\u0648\u0646\u06a9\u06c1 \u0644\u0627\u06af\u062a \u0635\u0641\u0631 \u06a9\u06d2 \u0642\u0631\u06cc\u0628 \u06c1\u0648\u062a\u06cc \u06c1\u06d2 \u0627\u0648\u0631 \u0627\u06af\u0631 \u0645\u0646\u0637\u0642 \u0628\u0627\u0644\u06a9\u0644 \u063a\u0644\u0637 \u06c1\u0648 \u062a\u0648 \u06a9\u0686\u06be \u0628\u06be\u06cc \u0645\u062e\u062a\u0644\u0641 \u0646\u06c1\u06cc\u06ba \u06c1\u0648\u062a\u0627\u06d4 \u0686\u06cc\u06a9 \u0628\u0627\u06a9\u0633 \u0627\u0628 \u0628\u06be\u06cc \u0679\u0648\u06af\u0644 \u06c1\u0648\u06af\u0627\u060c \u0644\u06cc\u06a9\u0646 \u06cc\u06c1 \u0635\u0631\u0641 \u063a\u0644\u0637 \u06a9\u0627\u0631\u0631\u0648\u0627\u0626\u06cc \u06a9\u0648 \u0679\u0648\u06af\u0644 \u06a9\u0631\u06d2 \u06af\u0627\u06d4<\/p>\n<p>\u0627\u06cc\u06a9 \u0639\u0627\u062f\u062a \u0627\u06cc\u0633\u06cc \u06c1\u06d2 \u062c\u0648 \u0628\u0686\u067e\u0646 \u0633\u06d2 \u06c1\u06cc \u0646\u0634\u0648\u0648\u0646\u0645\u0627 \u067e\u0627\u062a\u06cc \u06c1\u06d2\u06d4 <code>group<\/code> \u062a\u0642\u0631\u06cc\u0628\u0627 \u0627\u06cc\u06a9 \u062c\u06cc\u0633\u06d2 \u0679\u06cc\u0633\u0679\u0648\u06ba \u06a9\u0648 \u06a9\u0627\u067e\u06cc \u0627\u0648\u0631 \u067e\u06cc\u0633\u0679 \u06a9\u0631\u0646\u06d2 \u06a9\u06d2 \u0628\u062c\u0627\u0626\u06d2\u060c \u067e\u06cc\u0631\u0627\u0645\u06cc\u0679\u0631\u0627\u0626\u0632\u0688 \u0627\u0633\u0679\u0627\u0626\u0644 \u0644\u0648\u067e \u0627\u0633\u062a\u0639\u0645\u0627\u0644 \u06a9\u0631\u06cc\u06ba\u06d4 \u0645\u06cc\u06ba \u0627\u06cc\u06a9 \u06c1\u06cc \u0641\u0646\u06a9\u0634\u0646 \u06a9\u06d2 \u067e\u0627\u0646\u0686 \u0627\u0646\u062a\u06c1\u0627\u0626\u06cc \u06a9\u06cc\u0633\u0632 \u06a9\u06d2 \u0644\u06cc\u06d2 \u062a\u0642\u0631\u06cc\u0628\u0627\u064b \u0627\u06cc\u06a9 \u062c\u06cc\u0633\u06d2 \u0679\u06cc\u0633\u0679 \u0641\u0646\u06a9\u0634\u0646\u0632 \u0644\u06a9\u06be\u062a\u0627 \u062a\u06be\u0627\u060c \u0627\u0648\u0631 \u0644\u0627\u0645\u062d\u0627\u0644\u06c1 \u0627\u0646 \u067e\u0627\u0646\u0686\u0648\u06ba \u0645\u06cc\u06ba \u0633\u06d2 \u0627\u06cc\u06a9 \u0631\u06cc \u0641\u06cc\u06a9\u0679\u0631\u0646\u06af \u06a9\u06d2 \u0628\u0639\u062f \u062f\u0648\u0633\u0631\u0648\u06ba \u06a9\u06d2 \u0633\u0627\u062a\u06be \u06c1\u0645 \u0622\u06c1\u0646\u06af\u06cc \u0633\u06d2 \u0628\u0627\u06c1\u0631 \u06c1\u0648 \u062c\u0627\u0626\u06d2 \u06af\u0627\u06d4<\/p>\n<pre><code class=\"language-dart\">group('markDone with various ids', () {\n  final cases = <string bool=\"\">{\n    '1': true,   \/\/ exists, should be marked done\n    '2': false,  \/\/ exists, different id, should stay unchanged\n    'x': false,  \/\/ does not exist, should be a no-op\n  };\n\n  for (final entry in cases.entries) {\n    test('id ${entry.key} resolves to isDone=${entry.value}', () {\n      final tasks = [\n        const Task(id: '1', title: 'A'),\n        const Task(id: '2', title: 'B'),\n      ];\n      final result = markDone(tasks, '1');\n      final target = result.where(\n\n      if (target.isEmpty) {\n        \/\/ The 'x' case \u2014 id doesn't exist, list should be unaffected\n        expect(result.length, tasks.length);\n      } else {\n        expect(target.first.isDone, entry.value);\n      }\n    });\n  }\n});\n<\/string><\/code><\/pre>\n<p>\u06cc\u06c1 \u062f\u0648 \u06cc\u0627 \u062a\u06cc\u0646 \u06a9\u06cc\u0633\u0632 \u06a9\u06d2 \u0644\u06cc\u06d2 \u0633\u062e\u062a\u06cc \u0633\u06d2 \u0636\u0631\u0648\u0631\u06cc \u0646\u06c1\u06cc\u06ba \u06c1\u06d2\u060c \u0644\u06cc\u06a9\u0646 \u062c\u0633 \u0648\u0642\u062a \u06a9\u0633\u06cc \u0641\u0646\u06a9\u0634\u0646 \u06a9\u06cc \u062c\u0627\u0646\u0686 \u06a9\u06d2 \u0642\u0627\u0628\u0644 \u067e\u0627\u0646\u0686 \u06cc\u0627 \u0686\u06be \u0634\u0627\u062e\u06cc\u06ba \u06c1\u0648\u062a\u06cc \u06c1\u06cc\u06ba\u060c \u0627\u06cc\u06a9 \u0644\u0648\u067e \u0627\u0631\u0627\u062f\u06d2 \u06a9\u0648 \u067e\u0691\u06be\u0646\u06d2 \u06a9\u06d2 \u0642\u0627\u0628\u0644 \u0631\u06a9\u06be\u062a\u0627 \u06c1\u06d2 \u0627\u0648\u0631 \u0686\u06be\u0679\u06d2 \u06a9\u06cc\u0633 \u06a9\u0648 \u06a9\u0627\u067e\u06cc \u0627\u0648\u0631 \u067e\u06cc\u0633\u0679 \u06a9\u06cc\u06d2 \u06af\u0626\u06d2 \u0679\u06cc\u0633\u0679 \u0641\u0646\u06a9\u0634\u0646 \u06a9\u06d2 \u0628\u062c\u0627\u0626\u06d2 \u0627\u06cc\u06a9 \u0644\u0627\u0626\u0646 \u06a9\u06cc \u062a\u0628\u062f\u06cc\u0644\u06cc \u06a9\u06d2 \u0633\u0627\u062a\u06be \u062c\u0648\u0691\u062a\u0627 \u06c1\u06d2 \u062c\u0633\u06d2 \u06a9\u0648\u0626\u06cc \u0635\u062d\u06cc\u062d \u0637\u0631\u06cc\u0642\u06d2 \u0633\u06d2 \u0627\u067e \u0688\u06cc\u0679 \u06a9\u0631\u0646\u0627 \u0628\u06be\u0648\u0644 \u06af\u06cc\u0627 \u06c1\u06d2\u06d4<\/p>\n<h2 id=\"heading-testing-async-logic-and-exceptions\">\u063a\u06cc\u0631 \u0645\u0637\u0627\u0628\u0642\u062a \u067e\u0630\u06cc\u0631 \u0645\u0646\u0637\u0642 \u0627\u0648\u0631 \u0627\u0633\u062a\u062b\u0646\u0627\u0621 \u06a9\u06cc \u062c\u0627\u0646\u0686<\/h2>\n<p>\u062d\u0642\u06cc\u0642\u06cc \u0627\u06cc\u067e\u0633 \u0645\u06cc\u06ba \u0632\u06cc\u0627\u062f\u06c1 \u062a\u0631 \u062f\u0644\u0686\u0633\u067e \u0645\u0646\u0637\u0642 \u062e\u0627\u0644\u0635\u062a\u0627\u064b \u0645\u0637\u0627\u0628\u0642\u062a \u067e\u0630\u06cc\u0631 \u0646\u06c1\u06cc\u06ba \u06c1\u0648\u062a\u06cc\u06d4 \u06a9\u06cc\u0648\u0646\u06a9\u06c1 \u06cc\u06c1 \u063a\u06cc\u0631 \u0645\u0637\u0627\u0628\u0642\u062a \u067e\u0630\u06cc\u0631 \u06c1\u06d2\u060c \u06cc\u06c1 \u0646\u0627\u06a9\u0627\u0645 \u06c1\u0648 \u0633\u06a9\u062a\u0627 \u06c1\u06d2\u06d4 <code>flutter_test<\/code>\u0627\u06cc\u0633 <code>test()<\/code> \u06c1\u06cc\u0646\u0688\u0644 <code>Future<\/code>&#8211; \u06cc\u06c1 \u0628\u0627\u0688\u06cc \u06a9\u0648 \u0628\u0637\u0648\u0631 \u0688\u06cc\u0641\u0627\u0644\u0679 \u0648\u0627\u067e\u0633 \u06a9\u0631\u062a\u0627 \u06c1\u06d2\u060c \u062c\u0648 \u0644\u0648\u06af\u0648\u06ba \u06a9\u06cc \u062a\u0648\u0642\u0639 \u0633\u06d2 \u0632\u06cc\u0627\u062f\u06c1 \u0622\u0633\u0627\u0646 \u0628\u0646\u0627\u062a\u0627 \u06c1\u06d2\u060c \u0644\u06cc\u06a9\u0646 \u0627\u0633 \u06a9\u06d2 \u062e\u0648\u062f\u06a9\u0627\u0631 \u06c1\u0648\u0646\u06d2 \u0633\u06d2 \u067e\u06c1\u0644\u06d2 \u0645\u06cc\u06ba \u0646\u06d2 \u0628\u0627\u0631 \u0628\u0627\u0631 \u062f\u0648 \u063a\u0644\u0637\u06cc\u0627\u06ba \u06a9\u06cc\u06ba\u06d4<\/p>\n<pre><code class=\"language-dart\">test('setTaskDone throws for an unknown task id', () async {\n  final repository = FakeTaskRepository();\n\n  \/\/ expect() with throwsA works on synchronous throws.\n  \/\/ For a Future that completes with an error, you need\n  \/\/ expectLater with throwsA, or the async matcher form below.\n  await expectLater(\n    () => repository.setTaskDone('nonexistent', true),\n    throwsA(isA<tasknotfoundexception>()),\n  );\n});\n\ntest('fetchTasks returns an empty list, not null, when there is nothing to fetch', () async {\n  final repository = FakeTaskRepository(seed: []);\n\n  final result = await repository.fetchTasks();\n\n  \/\/ This looks trivial, but I've genuinely shipped a null check\n  \/\/ in a widget that assumed an empty repository always threw\n  \/\/ instead of returning []. One line here would have caught it.\n  expect(result, isEmpty);\n  expect(result, isNotNull);\n});\n<\/tasknotfoundexception><\/code><\/pre>\n<p>\u0645\u06cc\u0631\u06cc \u0633\u0628 \u0633\u06d2 \u0639\u0627\u0645 \u0627\u0628\u062a\u062f\u0627\u0626\u06cc \u063a\u0644\u0637\u06cc: \u0644\u06a9\u06be\u0646\u0627\u06d4 <code>expect(() => someAsyncFunction(), throwsA(...))<\/code> \u0628\u063a\u06cc\u0631 <code>await<\/code> \u0627\u0633 \u06a9\u06d2 \u0633\u0627\u0645\u0646\u06d2. \u0686\u0648\u0646\u06a9\u06c1 \u0679\u06cc\u0633\u0679 \u06a9\u06d2 \u062a\u062d\u062a \u0641\u0646\u06a9\u0634\u0646 \u063a\u06cc\u0631 \u0645\u0637\u0627\u0628\u0642\u062a \u067e\u0630\u06cc\u0631 \u06c1\u06d2\u060c \u0627\u0633\u062a\u062b\u0646\u0627\u0621 \u06c1\u06d2\u06d4 <code>Future<\/code> \u0627\u06af\u0631 \u06c1\u0645 \u0648\u0642\u062a \u0633\u0627\u0632 \u0645\u0633\u0626\u0644\u06c1 \u0627\u0628\u06be\u06cc \u062a\u06a9 \u062d\u0644 \u0646\u06c1\u06cc\u06ba \u06c1\u0648\u0627 \u06c1\u06d2\u06d4 <code>expect()<\/code> \u062f\u0648\u0691\u0648\u06d4 \u0686\u0648\u0646\u06a9\u06c1 \u062d\u0642\u06cc\u0642\u062a \u0645\u06cc\u06ba \u06a9\u0648\u0626\u06cc \u0628\u06be\u06cc \u0686\u06cc\u0632 \u0646\u0627\u06a9\u0627\u0645\u06cc \u06a9\u06d2 \u06c1\u0648\u0646\u06d2 \u06a9\u0627 \u0627\u0646\u062a\u0638\u0627\u0631 \u0646\u06c1\u06cc\u06ba \u06a9\u0631\u062a\u06cc \u06c1\u06d2\u060c \u0627\u0633 \u0644\u06cc\u06d2 \u06a9\u0648\u0688 \u0679\u0648\u0679 \u062c\u0627\u0646\u06d2 \u067e\u0631 \u0628\u06be\u06cc \u0679\u06cc\u0633\u0679 \u062e\u0648\u062f \u0628\u062e\u0648\u062f \u067e\u0627\u0633 \u06c1\u0648 \u062c\u0627\u062a\u0627 \u06c1\u06d2\u06d4 <code>expectLater<\/code> \u06a9\u06d2 \u0633\u0627\u062a\u06be \u0645\u0644 \u06a9\u0631 <code>await<\/code> \u06cc\u06c1 \u0648\u06c1 \u0648\u0631\u0698\u0646 \u06c1\u06d2 \u062c\u0648 \u062f\u0631\u0627\u0635\u0644 \u0646\u0627\u06a9\u0627\u0645\u06cc \u06a9\u0627 \u0631\u0627\u0633\u062a\u06c1 \u0686\u0644\u0627\u062a\u0627 \u06c1\u06d2\u06d4<\/p>\n<p><code>TaskScreen<\/code>    \u0686\u0627\u06c1\u06d2 \u06cc\u06c1 \u0644\u0648\u0688 \u06c1\u0648 \u0631\u06c1\u0627 \u06c1\u0648\u060c \u063a\u0644\u0637\u06cc\u0627\u06ba \u062f\u06a9\u06be\u0627 \u0631\u06c1\u0627 \u06c1\u0648\u060c \u06cc\u0627 \u0688\u06cc\u0679\u0627 \u0688\u0633\u067e\u0644\u06d2 \u06a9\u0631 \u0631\u06c1\u0627 \u06c1\u0648\u060c \u0627\u0633\u06d2 \u0635\u062d\u06cc\u062d \u0637\u0631\u06cc\u0642\u06d2 \u0633\u06d2 \u0631\u06cc\u0646\u0688\u0631 \u06a9\u0631\u0646\u06d2 \u06a9\u06cc \u0636\u0631\u0648\u0631\u062a \u06c1\u06d2\u06d4 \u0627\u0648\u0631 \u0645\u062c\u06be\u06d2 \u0627\u06cc\u06a9 \u062c\u0639\u0644\u06cc \u06a9\u06cc \u0636\u0631\u0648\u0631\u062a \u06c1\u06d2\u06d4 <code>TaskRepository<\/code> \u0627\u06cc\u06a9 \u062d\u0642\u06cc\u0642\u06cc \u0646\u06cc\u0679 \u0648\u0631\u06a9 \u06a9\u0627\u0644 \u06a9\u06cc\u06d2 \u0628\u063a\u06cc\u0631 \u0627\u06cc\u0633\u0627 \u06a9\u0631\u0646\u06d2 \u06a9\u06d2 \u0644\u06cc\u06d2\u06d4 <code>mocktail<\/code> \u06cc\u06c1 \u0688\u0627\u0631\u0679 \u0645\u06cc\u06ba \u0645\u0648\u062c\u0648\u062f\u06c1 \u0645\u0639\u06cc\u0627\u0631 \u06c1\u06d2 \u06a9\u06cc\u0648\u0646\u06a9\u06c1 \u0627\u0633\u06d2 \u067e\u0686\u06be\u0644\u06d2 \u0641\u0631\u0636\u06cc \u0637\u0631\u06cc\u0642\u0648\u06ba \u06a9\u06cc \u0637\u0631\u062d \u06a9\u0648\u0688 \u062c\u0646\u0631\u06cc\u0634\u0646 \u06a9\u06cc \u0636\u0631\u0648\u0631\u062a \u0646\u06c1\u06cc\u06ba \u06c1\u06d2\u06d4<\/p>\n<pre><code class=\"language-yaml\">dev_dependencies:\n  mocktail: ^1.0.4\n<\/code><\/pre>\n<pre><code class=\"language-dart\">\/\/ test\/task_screen_test.dart\nimport 'package:flutter\/material.dart';\nimport 'package:flutter_test\/flutter_test.dart';\nimport 'package:mocktail\/mocktail.dart';\nimport 'package:my_app\/task.dart';\nimport 'package:my_app\/task_notifier.dart';\nimport 'package:my_app\/task_repository.dart';\nimport 'package:my_app\/task_screen.dart';\n\nclass MockTaskRepository extends Mock implements TaskRepository {}\n\nvoid main() {\n  late MockTaskRepository repository;\n\n  setUp(() {\n    repository = MockTaskRepository();\n  });\n\n  testWidgets('shows a loading indicator while fetching', (tester) async {\n    \/\/ A Completer that never resolves keeps the widget in the\n    \/\/ loading state for the duration of this specific test.\n    repository.fetchTasks; \/\/ registered below via when()\n    when(() => repository.fetchTasks())\n        .thenAnswer((_) => Completer<list>>().future);\n\n    await tester.pumpWidget(MaterialApp(\n      home: TaskScreen(notifier: TaskNotifier(repository)),\n    ));\n\n    \/\/ pump() advances exactly one frame \u2014 enough to see the\n    \/\/ loading state, without waiting for anything to resolve.\n    await tester.pump();\n\n    expect(find.byType(CircularProgressIndicator), findsOneWidget);\n  });\n\n  testWidgets('shows tasks once loaded', (tester) async {\n    when(() => repository.fetchTasks()).thenAnswer(\n      (_) async => [\n        const Task(id: '1', title: 'Buy milk'),\n        const Task(id: '2', title: 'Walk the dog', isDone: true),\n      ],\n    );\n\n    await tester.pumpWidget(MaterialApp(\n      home: TaskScreen(notifier: TaskNotifier(repository)),\n    ));\n\n    \/\/ pumpAndSettle waits for all pending frames and microtasks \u2014\n    \/\/ the right call once you want to assert on the final,\n    \/\/ settled state rather than a specific frame along the way.\n    await tester.pumpAndSettle();\n\n    expect(find.text('Buy milk'), findsOneWidget);\n    expect(find.text('Tasks (1 done)'), findsOneWidget);\n  });\n\n  testWidgets('shows an error state with a working retry button', (tester) async {\n    when(() => repository.fetchTasks()).thenThrow(Exception('network error'));\n\n    await tester.pumpWidget(MaterialApp(\n      home: TaskScreen(notifier: TaskNotifier(repository)),\n    ));\n    await tester.pumpAndSettle();\n\n    expect(find.text('Failed to load tasks. Please try again.'), findsOneWidget);\n\n    \/\/ Now make the retry succeed, and confirm tapping Retry\n    \/\/ actually recovers \u2014 not just that the button exists.\n    when(() => repository.fetchTasks())\n        .thenAnswer((_) async => [const Task(id: '1', title: 'Buy milk')]);\n\n    await tester.tap(find.text('Retry'));\n    await tester.pumpAndSettle();\n\n    expect(find.text('Buy milk'), findsOneWidget);\n    expect(find.text('Failed to load tasks. Please try again.'), findsNothing);\n  });\n\n  testWidgets('completing a task updates the done count', (tester) async {\n    when(() => repository.fetchTasks()).thenAnswer(\n      (_) async => [const Task(id: '1', title: 'Buy milk')],\n    );\n    when(() => repository.setTaskDone('1', true)).thenAnswer((_) async {});\n\n    await tester.pumpWidget(MaterialApp(\n      home: TaskScreen(notifier: TaskNotifier(repository)),\n    ));\n    await tester.pumpAndSettle();\n\n    expect(find.text('Tasks (0 done)'), findsOneWidget);\n\n    await tester.tap(find.byType(CheckboxListTile));\n    await tester.pumpAndSettle();\n\n    expect(find.text('Tasks (1 done)'), findsOneWidget);\n  });\n}\n<\/list><\/code><\/pre>\n<p>\u062f\u0648\u0628\u0627\u0631\u06c1 \u06a9\u0648\u0634\u0634 \u06a9\u0631\u0646\u06d2 \u06a9\u0627 \u0679\u06cc\u0633\u0679 \u0627\u06cc\u06a9 \u0642\u0627\u0628\u0644 \u0630\u06a9\u0631 \u0627\u0645\u062a\u062d\u0627\u0646 \u06c1\u06d2\u06d4 \u06cc\u06c1 &quot;\u062f\u0648\u0628\u0627\u0631\u06c1 \u06a9\u0648\u0634\u0634 \u06a9\u0631\u0646\u06d2 \u0648\u0627\u0644\u0627 \u0628\u0679\u0646 \u0638\u0627\u06c1\u0631 \u06c1\u0648\u062a\u0627 \u06c1\u06d2&#8221; \u067e\u0631 \u0631\u06a9\u0646\u06d2 \u06a9\u06d2 \u0644\u06cc\u06d2 \u067e\u0631\u06a9\u0634\u0634 \u06c1\u06d2\u060c \u0644\u06cc\u06a9\u0646 \u0627\u0633 \u0633\u06d2 \u0635\u0631\u0641 \u06cc\u06c1 \u062b\u0627\u0628\u062a \u06c1\u0648\u062a\u0627 \u06c1\u06d2 \u06a9\u06c1 \u0628\u0679\u0646 \u0645\u0648\u062c\u0648\u062f \u06c1\u06d2 \u0627\u0648\u0631 \u0627\u0633\u06d2 \u0679\u06cc\u067e \u06a9\u0631\u0646\u06d2 \u0633\u06d2 \u06a9\u0686\u06be \u0646\u06c1\u06cc\u06ba \u06c1\u0648\u062a\u0627\u06d4 \u0628\u0627\u0632\u06cc\u0627\u0641\u062a \u0634\u062f\u06c1 \u062d\u0627\u0644\u062a \u06a9\u0627 \u0633\u0631\u0627\u063a \u0644\u06af\u0627\u0646\u0627 \u0627\u0648\u0631 \u0627\u0633 \u067e\u0631 \u0632\u0648\u0631 \u062f\u06cc\u0646\u0627 \u0627\u06cc\u06a9 \u062e\u0631\u0627\u0628 \u06a9\u0627\u0644 \u0628\u06cc\u06a9 \u06a9\u06d2 \u0633\u0627\u062a\u06be \u062f\u0648\u0628\u0627\u0631\u06c1 \u06a9\u0648\u0634\u0634 \u06a9\u0631\u0646\u06d2 \u0648\u0627\u0644\u06d2 \u0628\u0679\u0646 \u06a9\u0648 \u062c\u0648\u0691\u0646\u06d2 \u0633\u06d2 \u06af\u0631\u06cc\u0632 \u06a9\u0631\u0646\u0627 \u06c1\u06d2\u060c \u062c\u0648 \u06a9\u06c1 \u0639\u0645\u0644\u06cc \u0637\u0648\u0631 \u067e\u0631 \u06a9\u0631\u0646\u0627 \u0627\u06cc\u06a9 \u0622\u0633\u0627\u0646 \u063a\u0644\u0637\u06cc \u06c1\u06d2\u06d4<\/p>\n<p>\u0645\u06cc\u06ba \u0646\u06d2 \u0627\u0646 \u0633\u0628 \u06a9\u0648 \u0627\u06cc\u06a9 \u0633\u06d2 \u0632\u06cc\u0627\u062f\u06c1 \u0628\u0627\u0631 \u0628\u0646\u0627\u06cc\u0627 \u06c1\u06d2\u06d4<\/p>\n<h3 id=\"heading-1-using-pump-when-you-meant-pumpandsettle-or-the-reverse\">1. \u0627\u0633\u062a\u0639\u0645\u0627\u0644 \u06a9\u0631\u06cc\u06ba\u06d4 <code>pump()<\/code> \u062c\u0628 \u0622\u067e \u06a9\u0627 \u0645\u0637\u0644\u0628 \u062a\u06be\u0627 <code>pumpAndSettle()<\/code>\u06cc\u0627 \u0627\u0633 \u06a9\u06d2 \u0628\u0631\u0639\u06a9\u0633\u06d4<\/h3>\n<p><code>pump()<\/code>    \u0628\u0627\u0644\u06a9\u0644 \u0627\u06cc\u06a9 \u0641\u0631\u06cc\u0645 \u06a9\u0648 \u0622\u06af\u06d2 \u0628\u0691\u06be\u0627\u062a\u0627 \u06c1\u06d2\u06d4 <code>pumpAndSettle()<\/code> \u0641\u0631\u06cc\u0645 \u06a9\u0648 \u0627\u0633 \u0648\u0642\u062a \u062a\u06a9 \u067e\u0645\u067e \u06a9\u0631\u062a\u06d2 \u0631\u06c1\u06cc\u06ba \u062c\u0628 \u062a\u06a9 \u06a9\u06c1 \u0622\u067e \u0627\u0633\u06d2 \u062f\u0648\u0628\u0627\u0631\u06c1 \u0628\u0646\u0627\u0646\u06d2 \u06a9\u0627 \u0645\u0646\u0635\u0648\u0628\u06c1 \u0646\u06c1 \u0628\u0646\u0627\u0626\u06cc\u06ba\u06d4 \u063a\u06cc\u0631 \u0645\u0637\u0627\u0628\u0642\u062a \u067e\u0630\u06cc\u0631 \u0622\u067e\u0631\u06cc\u0634\u0646 \u0645\u06a9\u0645\u0644 \u06c1\u0648\u0646\u06d2 \u06a9\u06d2 \u0628\u0639\u062f \u0622\u067e \u06cc\u06c1\u06cc \u0686\u0627\u06c1\u062a\u06d2 \u06c1\u06cc\u06ba\u060c \u0644\u06cc\u06a9\u0646 \u0627\u06af\u0631 \u0648\u06cc\u062c\u06cc\u0679 \u0679\u0631\u06cc \u0645\u06cc\u06ba \u06a9\u0648\u0626\u06cc \u0686\u06cc\u0632 \u0645\u062a\u062d\u0631\u06a9 \u06c1\u0648\u062a\u06cc \u0631\u06c1\u062a\u06cc \u06c1\u06d2\u060c \u062a\u0648 \u06cc\u06c1 \u063a\u06cc\u0631 \u0645\u0639\u06cc\u0646\u06c1 \u0645\u062f\u062a \u062a\u06a9 \u0644\u0679\u06a9 \u062c\u0627\u0626\u06d2 \u06af\u06cc (\u0622\u062e\u0631 \u06a9\u0627\u0631 \u0648\u0642\u062a \u062e\u062a\u0645 \u06c1\u0648 \u062c\u0627\u0626\u06d2 \u06af\u0627)\u06d4 <code>CircularProgressIndicator<\/code>.<\/p>\n<p>\u0645\u06cc\u06ba \u06cc\u06c1 \u0633\u0645\u062c\u06be\u0646\u06d2 \u0633\u06d2 \u067e\u06c1\u0644\u06d2 \u0679\u06cc\u0633\u0679 \u0679\u0627\u0626\u0645 \u0622\u0624\u0679 \u06a9\u06d2 \u0628\u0627\u0631\u06d2 \u0645\u06cc\u06ba \u0627\u0644\u062c\u06be\u0646 \u0645\u06cc\u06ba \u067e\u0691 \u06af\u06cc\u0627 \u06c1\u0648\u06ba \u06a9\u06c1 \u0644\u0648\u0688\u0646\u06af \u0627\u0633\u067e\u0646\u0631 \u06c1\u06cc\u060c \u062c\u0633 \u0645\u06cc\u06ba \u0644\u0627\u0645\u062d\u062f\u0648\u062f \u0627\u06cc\u0646\u06cc\u0645\u06cc\u0634\u0646 \u06c1\u06d2\u060c \u0627\u0633 \u06a9\u06cc \u0648\u062c\u06c1 \u06a9\u06cc\u0627 \u06c1\u06d2\u06d4 <code>pumpAndSettle<\/code> \u0645\u06cc\u06ba \u0646\u06d2 \u067e\u06c1\u0644\u06d2 \u06a9\u0628\u06be\u06cc \u0645\u0646\u062c\u0645\u062f \u0641\u0631\u06cc\u0645 \u0646\u06c1\u06cc\u06ba \u062f\u06cc\u06a9\u06be\u0627\u06d4<\/p>\n<p>\u0622\u067e \u06a9\u06d2 \u0645\u062e\u0635\u0648\u0635 \u06a9\u06cc\u0633 \u0645\u06cc\u06ba \u062d\u0644 \u06a9\u0627\u0644 \u06a9\u0631\u0646\u0627 \u06c1\u06d2\u06d4 <code>pump()<\/code> \u0627\u0648\u0642\u0627\u062a \u06a9\u06cc \u0627\u06cc\u06a9 \u0645\u0642\u0631\u0631\u06c1 \u062a\u0639\u062f\u0627\u062f\u060c \u06cc\u0627 <code>pump(duration)<\/code> \u0627\u0633 \u06a9\u06d2 \u0628\u062c\u0627\u0626\u06d2\u060c \u0627\u06cc\u06a9 \u0648\u0627\u0636\u062d \u0645\u062f\u062a \u0627\u0633\u062a\u0639\u0645\u0627\u0644 \u06a9\u0631\u06cc\u06ba\u06d4 <code>pumpAndSettle()<\/code>\u062c\u0628 \u0628\u06be\u06cc \u0679\u06cc\u0633\u0679 \u06a9\u06d2 \u062a\u062d\u062a \u0648\u06cc\u062c\u06cc\u0679 \u0645\u06cc\u06ba \u06a9\u0648\u0626\u06cc \u0627\u06cc\u0633\u06cc \u0686\u06cc\u0632 \u06c1\u0648\u062a\u06cc \u06c1\u06d2 \u062c\u0633 \u06a9\u06cc \u062d\u0631\u06a9\u062a \u067e\u0630\u06cc\u0631\u06cc \u062c\u0627\u0626\u0632 \u0637\u0648\u0631 \u067e\u0631 \u0628\u0646\u062f \u0646\u06c1\u06cc\u06ba \u06c1\u0648\u062a\u06cc \u06c1\u06d2\u06d4<\/p>\n<pre><code class=\"language-dart\">\/\/ This will time out if the tree contains a CircularProgressIndicator,\n\/\/ which animates forever and never \"settles.\"\nawait tester.pumpAndSettle();\n\n\/\/ This advances a fixed number of frames instead \u2014 the right\n\/\/ choice when you specifically want to catch the loading state\n\/\/ mid-flight rather than wait for it to resolve.\nawait tester.pump();\nawait tester.pump(const Duration(milliseconds: 100));\n<\/code><\/pre>\n<h3 id=\"heading-2-finding-widgets-by-text-when-a-key-would-be-more-stable\">2. \u0645\u062a\u0646 \u06a9\u06d2 \u0630\u0631\u06cc\u0639\u06c1 \u0648\u06cc\u062c\u0679 \u062a\u0644\u0627\u0634 \u06a9\u0631\u06cc\u06ba\u06d4 <code>Key<\/code> \u06cc\u06c1 \u0632\u06cc\u0627\u062f\u06c1 \u0645\u0633\u062a\u062d\u06a9\u0645 \u06c1\u0648\u06af\u0627\u06d4<\/h3>\n<p><code>find.text('Buy milk')<\/code>    \u06cc\u06c1 \u0627\u0633 \u0644\u0645\u062d\u06d2 \u06a9\u0648 \u062a\u0648\u0691 \u062f\u06cc\u062a\u0627 \u06c1\u06d2 \u062c\u0628 \u067e\u0631\u0648\u0688\u06a9\u0679 \u06a9\u06cc \u06a9\u0627\u067e\u06cc \u062a\u0628\u062f\u06cc\u0644 \u06c1\u0648\u062a\u06cc \u06c1\u06d2\u060c \u06cc\u0627 \u0627\u06af\u0631 \u062f\u0648 \u06a9\u0627\u0645 \u0645\u0633\u062a\u0642\u0628\u0644 \u06a9\u06d2 \u0679\u06cc\u0633\u0679\u0648\u06ba \u0645\u06cc\u06ba \u0627\u06cc\u06a9 \u0639\u0646\u0648\u0627\u0646 \u06a9\u0627 \u0627\u0634\u062a\u0631\u0627\u06a9 \u06a9\u0631\u062a\u06d2 \u06c1\u06cc\u06ba\u06d4 \u0627\u0628 \u06c1\u0631 \u0648\u06c1 \u0686\u06cc\u0632 \u062f\u0631\u062c \u06a9\u0631\u06cc\u06ba \u062c\u0648 \u0622\u067e \u06a9\u0648 \u0679\u06cc\u0633\u0679 \u0645\u06cc\u06ba \u0642\u0627\u0628\u0644 \u0627\u0639\u062a\u0645\u0627\u062f \u0637\u0631\u06cc\u0642\u06d2 \u0633\u06d2 \u062a\u0644\u0627\u0634 \u06a9\u0631\u0646\u06d2 \u06a9\u06cc \u0636\u0631\u0648\u0631\u062a \u06c1\u06d2\u060c \u0627\u0633\u06cc \u0637\u0631\u062d\u06d4 <code>CheckboxListTile<\/code> \u0645\u0646\u062f\u0631\u062c\u06c1 \u0628\u0627\u0644\u0627 \u0686\u0627\u0628\u06cc\u0627\u06ba \u06c1\u06cc\u06ba: <code>ValueKey(task.id)<\/code>: <code>find.byKey(const ValueKey('1'))<\/code> \u0645\u062c\u06be\u06d2 \u0627\u0633 \u0633\u06d2 \u06a9\u0648\u0626\u06cc \u0641\u0631\u0642 \u0646\u06c1\u06cc\u06ba \u067e\u0691\u062a\u0627 \u06a9\u06c1 \u0646\u0648\u06a9\u0631\u06cc \u06a9\u0627 \u0639\u0646\u0648\u0627\u0646 \u06a9\u06cc\u0627 \u06c1\u06d2\u06d4<\/p>\n<h3 id=\"heading-3-forgetting-that-materialapp-wraps-every-widget-test-that-touches-themeofcontext-or-navigator\">3. \u0627\u0633\u06d2 \u0628\u06be\u0648\u0644 \u062c\u0627\u0646\u0627 <code>MaterialApp<\/code> \u0627\u0633 \u06a9\u06d2 \u0686\u06be\u0648\u0646\u06d2 \u0648\u0627\u0644\u06d2 \u062a\u0645\u0627\u0645 \u0648\u06cc\u062c\u06cc\u0679 \u0679\u06cc\u0633\u0679\u0648\u06ba \u06a9\u0648 \u0644\u067e\u06cc\u0679 \u062f\u06cc\u062a\u0627 \u06c1\u06d2\u06d4 <code>Theme.of(context)<\/code> \u06cc\u0627 <code>Navigator<\/code>.<\/h3>\n<p>\u062f\u0648\u0631 \u0627\u0646\u062f\u06cc\u0634\u06cc <code>pumpWidget(TaskScreen(...))<\/code> \u0628\u063a\u06cc\u0631 <code>MaterialApp<\/code> \u0627\u062c\u062f\u0627\u062f \u06af\u0645\u0634\u062f\u06af\u06cc \u06a9\u06d2 \u0628\u0627\u0631\u06d2 \u0645\u06cc\u06ba \u0627\u06cc\u06a9 \u0645\u0628\u06c1\u0645 \u063a\u0644\u0637\u06cc \u067e\u06be\u06cc\u0646\u06a9\u062a\u0627 \u06c1\u06d2\u06d4 <code>Directionality<\/code> \u06cc\u0627 <code>Navigator<\/code> \u067e\u06c1\u0644\u06cc \u0628\u0627\u0631 \u062c\u0628 \u06a9\u0648\u0626\u06cc \u0648\u06cc\u062c\u06cc\u0679 \u06a9\u0633\u06cc \u0627\u06cc\u0633\u06d2 \u0622\u067e\u0631\u06cc\u0634\u0646 \u06a9\u06cc \u06a9\u0648\u0634\u0634 \u06a9\u0631\u062a\u0627 \u06c1\u06d2 \u062c\u0648 \u062f\u0648\u0646\u0648\u06ba \u067e\u0631 \u0645\u0646\u062d\u0635\u0631 \u06c1\u0648\u062a\u0627 \u06c1\u06d2\u06d4 \u06cc\u06c1 \u0648\u06c1 \u063a\u0644\u0637\u06cc \u06a9\u0627 \u067e\u06cc\u063a\u0627\u0645 \u06c1\u06d2 \u062c\u0648 \u0622\u067e \u06a9\u0648 \u067e\u06c1\u0644\u06cc \u0686\u0646\u062f \u0628\u0627\u0631 \u0645\u0627\u0631\u0646\u06d2 \u067e\u0631 \u0645\u0644\u062a\u0627 \u06c1\u06d2\u060c \u062c\u0648 \u0638\u0627\u06c1\u0631 \u06c1\u06d2 &quot;\u0645\u0679\u06cc\u0631\u06cc\u0644 \u0627\u06cc\u067e \u0645\u06cc\u06ba \u0644\u067e\u06cc\u0679&#8221; \u06a9\u06cc \u0637\u0631\u0641 \u0627\u0634\u0627\u0631\u06c1 \u0646\u06c1\u06cc\u06ba \u06a9\u0631\u062a\u0627 \u06c1\u06d2\u06d4<\/p>\n<h2 id=\"heading-testing-text-input-and-scrolling\">\u0679\u06cc\u06a9\u0633\u0679 \u0627\u0646 \u067e\u0679 \u0627\u0648\u0631 \u0627\u0633\u06a9\u0631\u0648\u0644\u0646\u06af \u06a9\u06cc \u062c\u0627\u0646\u0686 \u06a9\u0631\u06cc\u06ba\u06d4<\/h2>\n<p>\u06cc\u06c1 \u062f\u0648 \u062a\u0639\u0627\u0645\u0644\u0627\u062a &#8211; \u06a9\u0633\u06cc \u0641\u06cc\u0644\u0688 \u0645\u06cc\u06ba \u0679\u0627\u0626\u067e \u06a9\u0631\u0646\u0627 \u0627\u0648\u0631 \u0622\u0641 \u0627\u0633\u06a9\u0631\u06cc\u0646 \u0645\u0648\u0627\u062f \u06a9\u0648 \u0638\u0627\u06c1\u0631 \u06a9\u0631\u0646\u06d2 \u06a9\u06d2 \u0644\u06cc\u06d2 \u0627\u0633\u06a9\u0631\u0648\u0644 \u06a9\u0631\u0646\u0627 &#8211; \u0627\u06a9\u062b\u0631 \u0627\u06cc\u0633\u0627 \u06c1\u0648\u062a\u0627 \u06c1\u06d2 \u06a9\u06c1 \u0627\u067e\u0646\u06d2 \u0637\u0648\u0631 \u067e\u0631 \u0627\u0633 \u06a9\u06cc \u0645\u062b\u0627\u0644 \u062f\u06cc\u0646\u06d2 \u06a9\u06d2 \u0642\u0627\u0628\u0644 \u06c1\u0648\u06d4<\/p>\n<pre><code class=\"language-dart\">testWidgets('typing a name and submitting calls the repository', (tester) async {\n  final repository = MockTaskRepository();\n  when(() => repository.fetchTasks()).thenAnswer((_) async => []);\n  when(() => repository.addTask(any())).thenAnswer((_) async {});\n\n  await tester.pumpWidget(MaterialApp(\n    home: TaskScreen(notifier: TaskNotifier(repository)),\n  ));\n  await tester.pumpAndSettle();\n\n  \/\/ enterText simulates typing directly \u2014 no need to simulate\n  \/\/ individual keystrokes for the overwhelming majority of tests.\n  await tester.enterText(find.byKey(const Key('new_task_field')), 'Buy milk');\n  await tester.tap(find.byKey(const Key('add_task_button')));\n  await tester.pumpAndSettle();\n\n  verify(() => repository.addTask('Buy milk')).called(1);\n});\n\ntestWidgets('scrolling reveals a task below the fold', (tester) async {\n  final repository = MockTaskRepository();\n  when(() => repository.fetchTasks()).thenAnswer(\n    (_) async => List.generate(\n      30,\n      (i) => Task(id: '$i', title: 'Task $i'),\n    ),\n  );\n\n  await tester.pumpWidget(MaterialApp(\n    home: TaskScreen(notifier: TaskNotifier(repository)),\n  ));\n  await tester.pumpAndSettle();\n\n  \/\/ Task 25 is off-screen on first render in a 30-item list.\n  expect(find.text('Task 25'), findsNothing);\n\n  \/\/ scrollUntilVisible repeatedly scrolls a fixed amount and\n  \/\/ checks after each attempt \u2014 the right tool when you don't\n  \/\/ know exactly how far to scroll to reach a specific item.\n  await tester.scrollUntilVisible(\n    find.text('Task 25'),\n    500.0,\n    scrollable: find.byType(Scrollable),\n  );\n\n  expect(find.text('Task 25'), findsOneWidget);\n});\n<\/code><\/pre>\n<h2 id=\"heading-golden-tests-catching-visual-regressions\">\u06af\u0648\u0644\u0688\u0646 \u0679\u06cc\u0633\u0679: \u0628\u0635\u0631\u06cc \u0631\u062c\u0639\u062a \u06a9\u0648 \u067e\u06a9\u0691\u0646\u0627<\/h2>\n<p>\u0627\u0628 \u062a\u06a9 \u062a\u0645\u0627\u0645 \u0679\u06cc\u0633\u0679 \u06c1\u0648 \u0686\u06a9\u06d2 \u06c1\u06cc\u06ba\u06d4 <em>\u06a9\u0627\u0631\u0631\u0648\u0627\u0626\u06cc<\/em>: \u062f\u0631\u0633\u062a \u0645\u062a\u0646 \u0638\u0627\u06c1\u0631 \u06c1\u0648\u062a\u0627 \u06c1\u06d2 \u06cc\u0627 \u062f\u0631\u0633\u062a \u0634\u0645\u0627\u0631 \u06a9\u0648 \u0627\u067e \u0688\u06cc\u0679 \u06a9\u06cc\u0627 \u062c\u0627\u062a\u0627 \u06c1\u06d2\u06d4 \u0627\u0646 \u0645\u06cc\u06ba \u0633\u06d2 \u06a9\u0648\u0626\u06cc \u0628\u06be\u06cc \u0627\u06cc\u0633\u06cc \u062a\u0628\u062f\u06cc\u0644\u06cc\u0648\u06ba \u06a9\u0648 \u0646\u06c1\u06cc\u06ba \u067e\u06a9\u0691\u06d2 \u06af\u0627 \u062c\u0633 \u06a9\u06cc \u0648\u062c\u06c1 \u0633\u06d2 \u0686\u06be\u0648\u0679\u06cc \u0627\u0633\u06a9\u0631\u06cc\u0646\u0648\u06ba \u067e\u0631 \u0686\u06cc\u06a9 \u0628\u0627\u06a9\u0633 \u06a9\u06cc \u0641\u06c1\u0631\u0633\u062a \u06a9\u0646\u0679\u06cc\u0646\u0631 \u06a9\u0648 \u0627\u0648\u0648\u0631 \u0641\u0644\u0648 \u06a9\u0631\u062a\u06cc \u06c1\u06d2\u060c \u06cc\u0627 \u067e\u06cc\u0688\u0646\u06af \u0627\u06cc\u0688\u062c\u0633\u0679\u0645\u0646\u0679 \u062c\u0648 \u062f\u0648\u0628\u0627\u0631\u06c1 \u06a9\u0648\u0634\u0634 \u06a9\u0631\u0646\u06d2 \u06a9\u06d2 \u0628\u0679\u0646 \u06a9\u0648 \u0627\u0633\u06a9\u0631\u06cc\u0646 \u0633\u06d2 \u062f\u0648\u0631 \u06a9\u0631\u062a\u06cc \u06c1\u06d2\u06d4 \u06cc\u06c1\u06cc \u0648\u062c\u06c1 \u06c1\u06d2 \u06a9\u06c1 \u0633\u0646\u06c1\u0631\u06cc \u0627\u0645\u062a\u062d\u0627\u0646 \u0645\u0648\u062c\u0648\u062f \u06c1\u06d2\u06d4<\/p>\n<p>\u06af\u0648\u0644\u0688\u0646 \u0679\u06cc\u0633\u0679 \u0648\u06cc\u062c\u06cc\u0679 \u06a9\u0648 \u067e\u06cc\u0634 \u06a9\u0631\u062a\u0627 \u06c1\u06d2 \u0627\u0648\u0631 \u0627\u0633 \u06a9\u0627 \u0645\u0648\u0627\u0632\u0646\u06c1 \u0627\u06cc\u06a9 \u0630\u062e\u06cc\u0631\u06c1 \u0634\u062f\u06c1 \u062d\u0648\u0627\u0644\u06c1 \u062a\u0635\u0648\u06cc\u0631 \u0633\u06d2 \u067e\u06a9\u0633\u0644 \u0628\u06c1 \u067e\u06a9\u0633\u0644 \u06a9\u0631\u062a\u0627 \u06c1\u06d2\u06d4<\/p>\n<pre><code class=\"language-dart\">\/\/ test\/task_screen_golden_test.dart\nimport 'package:flutter\/material.dart';\nimport 'package:flutter_test\/flutter_test.dart';\nimport 'package:mocktail\/mocktail.dart';\nimport 'package:my_app\/task.dart';\nimport 'package:my_app\/task_notifier.dart';\nimport 'package:my_app\/task_repository.dart';\nimport 'package:my_app\/task_screen.dart';\n\nclass MockTaskRepository extends Mock implements TaskRepository {}\n\nvoid main() {\n  testWidgets('task screen with data matches the golden file', (tester) async {\n    final repository = MockTaskRepository();\n    when(() => repository.fetchTasks()).thenAnswer(\n      (_) async => [\n        const Task(id: '1', title: 'Buy milk'),\n        const Task(id: '2', title: 'Walk the dog', isDone: true),\n      ],\n    );\n\n    await tester.pumpWidget(MaterialApp(\n      home: TaskScreen(notifier: TaskNotifier(repository)),\n    ));\n    await tester.pumpAndSettle();\n\n    \/\/ On first run, this generates the reference image.\n    \/\/ On every run after, it fails if a single pixel differs.\n    await expectLater(\n      find.byType(TaskScreen),\n      matchesGoldenFile('goldens\/task_screen_with_data.png'),\n    );\n  });\n\n  testWidgets('task screen error state matches the golden file', (tester) async {\n    final repository = MockTaskRepository();\n    when(() => repository.fetchTasks()).thenThrow(Exception('error'));\n\n    await tester.pumpWidget(MaterialApp(\n      home: TaskScreen(notifier: TaskNotifier(repository)),\n    ));\n    await tester.pumpAndSettle();\n\n    await expectLater(\n      find.byType(TaskScreen),\n      matchesGoldenFile('goldens\/task_screen_error.png'),\n    );\n  });\n}\n<\/code><\/pre>\n<p>\u0627\u0633\u062a\u0639\u0645\u0627\u0644 \u06a9\u0631\u062a\u06d2 \u06c1\u0648\u0626\u06d2 \u0627\u06cc\u06a9 \u0627\u0628\u062a\u062f\u0627\u0626\u06cc \u062d\u0648\u0627\u0644\u06c1 \u062a\u0635\u0648\u06cc\u0631 \u0628\u0646\u0627\u0626\u06cc\u06ba:<\/p>\n<pre><code class=\"language-bash\">flutter test --update-goldens test\/task_screen_golden_test.dart\n<\/code><\/pre>\n<p>\u0639\u0632\u0645 \u067e\u06cc\u062f\u0627 \u06a9\u06cc\u0627 <code>.png<\/code> \u0679\u06cc\u0633\u0679 \u06a9\u06d2 \u0633\u0627\u062a\u06be \u0641\u0627\u0626\u0644 \u06a9\u0631\u06cc\u06ba\u06d4 \u062a\u0628 \u0633\u06d2\u060c <code>flutter test<\/code> \u062f\u0648\u0628\u0627\u0631\u06c1 \u062a\u062e\u0644\u06cc\u0642 \u06a9\u0631\u0646\u06d2 \u06a9\u06d2 \u0628\u062c\u0627\u0626\u06d2 \u0645\u0648\u0627\u0632\u0646\u06c1 \u06a9\u0631\u06cc\u06ba\u06d4 \u0627\u06af\u0631 \u0645\u0633\u062a\u0642\u0628\u0644 \u0645\u06cc\u06ba \u062a\u0628\u062f\u06cc\u0644\u06cc \u067e\u06a9\u0633\u0644\u0632 \u06a9\u0648 \u062a\u0628\u062f\u06cc\u0644 \u06a9\u0631\u0646\u06d2 \u06a9\u0627 \u0633\u0628\u0628 \u0628\u0646\u062a\u06cc \u06c1\u06d2\u060c \u062a\u0648 \u0679\u06cc\u0633\u0679 \u0646\u0627\u06a9\u0627\u0645 \u06c1\u0648 \u062c\u0627\u0626\u06d2 \u06af\u0627 \u0627\u0648\u0631 \u0641\u0631\u0642 \u0638\u0627\u06c1\u0631 \u06a9\u0631\u06d2 \u06af\u0627\u060c \u0628\u062c\u0627\u0626\u06d2 \u0627\u0633 \u06a9\u06d2 \u06a9\u06c1 \u0622\u067e \u06a9\u06cc \u0679\u06cc\u0645 \u062a\u06cc\u0646 \u0627\u0633\u067e\u0631\u0646\u0679 \u06a9\u06d2 \u0628\u0639\u062f \u0627\u0635\u0644\u06cc \u0688\u06cc\u0648\u0627\u0626\u0633 \u067e\u0631 \u0627\u0633\u06a9\u0631\u06cc\u0646 \u06a9\u0648 \u062f\u06cc\u06a9\u06be \u06a9\u0631 \u062a\u06be\u0648\u0691\u0627 \u0633\u0627 \u0639\u062c\u06cc\u0628 \u0644\u06af\u062a\u06cc \u06c1\u06d2\u06d4<\/p>\n<p>\u0627\u0633 \u067e\u0631 \u0628\u06c1\u062a \u0632\u06cc\u0627\u062f\u06c1 \u0627\u0646\u062d\u0635\u0627\u0631 \u06a9\u0631\u0646\u06d2 \u0633\u06d2 \u067e\u06c1\u0644\u06d2 \u062f\u0648 \u0627\u0646\u062a\u0628\u0627\u06c1\u0627\u062a \u0633\u06d2 \u0622\u06af\u0627\u06c1 \u06c1\u0648\u0646\u0627 \u0636\u0631\u0648\u0631\u06cc \u06c1\u06d2: \u067e\u06c1\u0644\u0627\u060c \u0641\u0648\u0646\u0679\u0633 \u0627\u0648\u0631 \u0631\u06cc\u0646\u0688\u0631\u0646\u06af \u0622\u067e \u06a9\u06d2 \u06a9\u0645\u067e\u06cc\u0648\u0679\u0631 \u0627\u0648\u0631 CI \u0627\u06cc\u06af\u0632\u06cc\u06a9\u06cc\u0648\u0679\u0631 \u06a9\u06d2 \u062f\u0631\u0645\u06cc\u0627\u0646 \u0628\u0627\u0644\u06a9\u0644 \u0645\u062e\u062a\u0644\u0641 \u06c1\u0648 \u0633\u06a9\u062a\u06d2 \u06c1\u06cc\u06ba\u060c \u062c\u0633 \u06a9\u06cc \u0648\u062c\u06c1 \u0633\u06d2 \u063a\u0644\u0637 \u063a\u0644\u0637\u06cc\u0627\u06ba \u06c1\u0648 \u0633\u06a9\u062a\u06cc \u06c1\u06cc\u06ba \u062c\u0646 \u06a9\u0627 \u0622\u067e \u06a9\u06d2 \u06a9\u0648\u0688 \u0633\u06d2 \u06a9\u0648\u0626\u06cc \u062a\u0639\u0644\u0642 \u0646\u06c1\u06cc\u06ba \u06c1\u06d2\u06d4 \u06af\u0648\u0644\u0688\u0646 \u06a9\u0648 \u0645\u0633\u062a\u0642\u0644 \u0688\u0648\u06a9\u0631 \u0627\u0645\u06cc\u062c \u06a9\u06d2 \u0627\u0646\u062f\u0631 \u0686\u0644\u0627\u0626\u06cc\u06ba \u06cc\u0627 \u0627\u0633 \u0637\u0631\u062d \u06a9\u0627 \u067e\u06cc\u06a9\u06cc\u062c \u0627\u0633\u062a\u0639\u0645\u0627\u0644 \u06a9\u0631\u06cc\u06ba: <code>golden_toolkit<\/code> (\u0645\u0639\u06cc\u0627\u0631\u06cc \u0641\u0648\u0646\u0679 \u0644\u0648\u0688\u0646\u06af) \u0627\u0633 \u0645\u0633\u0626\u0644\u06d2 \u0645\u06cc\u06ba \u0633\u06d2 \u0632\u06cc\u0627\u062f\u06c1 \u062a\u0631 \u062d\u0644 \u06a9\u0631\u062a\u0627 \u06c1\u06d2\u06d4<\/p>\n<p>\u062f\u0648\u0633\u0631\u0627\u060c \u06af\u0648\u0644\u0688\u0646 \u0627\u0646 \u0627\u0633\u06a9\u0631\u06cc\u0646\u0648\u06ba \u067e\u0631 \u0628\u0631\u0642\u0631\u0627\u0631 \u0631\u06a9\u06be\u0646\u0627 \u0645\u06c1\u0646\u06af\u0627 \u06c1\u06d2 \u062c\u0648 \u0641\u0639\u0627\u0644 \u0646\u0634\u0648\u0648\u0646\u0645\u0627 \u06a9\u06d2 \u062f\u0648\u0631\u0627\u0646 \u0627\u06a9\u062b\u0631 \u062a\u0628\u062f\u06cc\u0644 \u06c1\u0648\u062a\u06cc \u06c1\u06cc\u06ba\u06d4 \u06c1\u0631 \u0628\u0627\u0631 \u062c\u0628 \u0622\u067e \u0644\u06d2 \u0622\u0624\u0679 \u06a9\u0648 \u0627\u06cc\u0688\u062c\u0633\u0679 \u06a9\u0631\u062a\u06d2 \u06c1\u06cc\u06ba \u062a\u0648 \u06af\u0648\u0644\u0688\u0646 \u06a9\u0648 \u062f\u0648\u0628\u0627\u0631\u06c1 \u0628\u0646\u0627\u0646\u0627 \u0645\u0642\u0635\u062f \u06a9\u0648 \u0646\u0627\u06a9\u0627\u0645 \u0628\u0646\u0627 \u062f\u06cc\u062a\u0627 \u06c1\u06d2\u060c \u0627\u0633 \u0644\u06cc\u06d2 \u0627\u0633\u06d2 \u0628\u0627\u0642\u06cc \u0686\u06cc\u0632\u0648\u06ba \u06a9\u06d2 \u0628\u062c\u0627\u0626\u06d2 \u0645\u0633\u062a\u062d\u06a9\u0645\u060c \u0632\u06cc\u0627\u062f\u06c1 \u0645\u0631\u0626\u06cc \u0627\u0633\u06a9\u0631\u06cc\u0646\u0648\u06ba \u06a9\u06d2 \u0644\u06cc\u06d2 \u0645\u062d\u0641\u0648\u0638 \u06a9\u0631\u06cc\u06ba\u06d4<\/p>\n<h2 id=\"heading-multi-device-and-dark-mode-goldens\">\u0645\u0644\u0679\u06cc \u0688\u06cc\u0648\u0627\u0626\u0633 \u0627\u0648\u0631 \u0688\u0627\u0631\u06a9 \u0645\u0648\u0688 \u06af\u0648\u0644\u0688\u0646<\/h2>\n<p>\u0627\u06cc\u06a9 \u0633\u0646\u06c1\u0631\u06cc \u062a\u0635\u0648\u06cc\u0631 \u0635\u0631\u0641 \u06cc\u06c1 \u062b\u0627\u0628\u062a \u06a9\u0631\u062a\u06cc \u06c1\u06d2 \u06a9\u06c1 \u0627\u0633\u06a9\u0631\u06cc\u0646 \u0627\u06cc\u06a9 \u062a\u06be\u06cc\u0645 \u0627\u0648\u0631 \u0627\u06cc\u06a9 \u0627\u0633\u06a9\u0631\u06cc\u0646 \u0633\u0627\u0626\u0632 \u0645\u06cc\u06ba \u062f\u0631\u0633\u062a \u0646\u0638\u0631 \u0622\u062a\u06cc \u06c1\u06d2\u06d4 \u0645\u06cc\u06ba \u0646\u06d2 \u0627\u0635\u0644 \u0645\u06cc\u06ba \u062c\u0648 \u0628\u06af \u067e\u0627\u06cc\u0627 \u0648\u06c1 \u06cc\u06c1 \u062a\u06be\u0627 \u06a9\u06c1 \u0648\u0631\u06a9\u0646\u06af \u0679\u0627\u0626\u0679\u0644\u060c \u062c\u0633\u06d2 \u0645\u0639\u06cc\u0627\u0631\u06cc \u0641\u0648\u0646 \u06a9\u06cc \u0686\u0648\u0691\u0627\u0626\u06cc \u067e\u0631 \u0635\u0627\u0641 \u0633\u062a\u06be\u0631\u0627 \u06a9\u0631\u067e \u06a9\u06cc\u0627 \u06af\u06cc\u0627 \u062a\u06be\u0627\u060c \u0686\u06be\u0648\u0679\u06cc \u0627\u0633\u06a9\u0631\u06cc\u0646 \u0688\u06cc\u0648\u0627\u0626\u0633\u0632 \u067e\u0631 9 \u067e\u06a9\u0633\u0644\u0632 \u062a\u06a9 \u067e\u06be\u06cc\u0644 \u06af\u06cc\u0627\u060c \u0627\u0648\u0631 \u06a9\u0633\u06cc \u0646\u06d2 \u0627\u0633 \u0648\u0642\u062a \u062a\u06a9 \u062a\u0648\u062c\u06c1 \u0646\u06c1\u06cc\u06ba \u062f\u06cc \u062c\u0628 \u062a\u06a9 \u06a9\u06c1 \u067e\u0631\u0627\u0646\u06d2\u060c \u062a\u0646\u06af \u0641\u0648\u0646 \u06a9\u0627 \u0627\u0633\u062a\u0639\u0645\u0627\u0644 \u06a9\u0631\u0646\u06d2 \u0648\u0627\u0644\u06d2 \u06a9\u0633\u06cc \u06a9\u06cc \u0637\u0631\u0641 \u0633\u06d2 \u0633\u067e\u0648\u0631\u0679 \u0679\u06a9\u0679 \u0646\u06c1 \u0622\u0626\u06d2\u06d4<\/p>\n<p><code>golden_toolkit<\/code>\u0627\u06cc\u0633 <code>multiScreenGolden<\/code> \u0627\u06cc\u06a9 \u06c1\u06cc \u0679\u06cc\u0633\u0679 \u0645\u06cc\u06ba \u0627\u06cc\u06a9 \u06c1\u06cc \u0648\u06cc\u062c\u06cc\u0679 \u06a9\u0648 \u0645\u062a\u0639\u062f\u062f \u0688\u06cc\u0648\u0627\u0626\u0633 \u0633\u0627\u0626\u0632\u0632 \u0645\u06cc\u06ba \u0631\u06cc\u0646\u0688\u0631 \u06a9\u0631\u06cc\u06ba\u06d4 \u06cc\u06c1 \u0648\u06c1 \u0648\u0631\u0698\u0646 \u06c1\u06d2 \u062c\u0648 \u0645\u06cc\u06ba \u0627\u0646 \u062a\u0645\u0627\u0645 \u0627\u0633\u06a9\u0631\u06cc\u0646\u0648\u06ba \u067e\u0631 \u0627\u0633\u062a\u0639\u0645\u0627\u0644 \u06a9\u0631\u062a\u0627 \u06c1\u0648\u06ba \u062c\u0646 \u06a9\u06cc \u0645\u06cc\u06ba \u0633\u0646\u06c1\u0631\u06cc \u062c\u0627\u0646\u0686 \u06a9\u0631 \u0631\u06c1\u0627 \u06c1\u0648\u06ba\u06d4<\/p>\n<pre><code class=\"language-yaml\">dev_dependencies:\n  golden_toolkit: ^0.15.0\n<\/code><\/pre>\n<pre><code class=\"language-dart\">testGoldens('task screen across device sizes', (tester) async {\n  final repository = MockTaskRepository();\n  when(() => repository.fetchTasks()).thenAnswer(\n    (_) async => [const Task(id: '1', title: 'Buy milk, eggs, and bread')],\n  );\n\n  final builder = DeviceBuilder()\n    ..overrideDevicesForAllScenarios(devices: [\n      Device.phone,       \/\/ narrow \u2014 this is the one that caught the overflow\n      Device.iphone11,\n      Device.tabletLandscape,\n    ])\n    ..addScenario(\n      widget: MaterialApp(home: TaskScreen(notifier: TaskNotifier(repository))),\n      name: 'with data',\n    );\n\n  await tester.pumpDeviceBuilder(builder);\n  await screenMatchesGolden(tester, 'task_screen_multi_device');\n});\n<\/code><\/pre>\n<p>\u0627\u06af\u0631 \u0622\u067e \u06a9\u06cc \u0627\u06cc\u067e \u0627\u0633 \u06a9\u06cc \u062d\u0645\u0627\u06cc\u062a \u06a9\u0631\u062a\u06cc \u06c1\u06d2 \u062a\u0648 \u0688\u0627\u0631\u06a9 \u0645\u0648\u0688 \u0627\u0633\u06cc \u067e\u0631\u0648\u0633\u06cc\u0633\u0646\u06af \u06a9\u06d2 \u0642\u0627\u0628\u0644 \u06c1\u06d2\u06d4 \u06c1\u0627\u0631\u0688 \u06a9\u0648\u0688\u0688 \u0679\u06cc\u06a9\u0633\u0679 \u06a9\u0644\u0631 \u062c\u0648 \u06a9\u06c1 \u06af\u06c1\u0631\u06d2 \u067e\u0633 \u0645\u0646\u0638\u0631 \u0645\u06cc\u06ba \u067e\u0648\u0634\u06cc\u062f\u06c1 \u06c1\u0648\u062a\u06d2 \u06c1\u06cc\u06ba \u06a9\u06cc\u0691\u06d2 \u06a9\u06cc \u0627\u06cc\u06a9 \u062d\u0642\u06cc\u0642\u06cc \u0634\u0631\u0645\u0646\u0627\u06a9 \u06a9\u0644\u0627\u0633 \u06c1\u06cc\u06ba\u060c \u0627\u0648\u0631 \u0627\u06af\u0631 \u0622\u067e \u06a9\u06d2 \u062a\u0645\u0627\u0645 \u0633\u0646\u06c1\u0631\u06cc \u0679\u06cc\u0633\u0679 \u0635\u0631\u0641 \u0644\u0627\u0626\u0679 \u0645\u0648\u0688 \u0645\u06cc\u06ba \u067e\u06cc\u0634 \u06a9\u06cc\u06d2 \u062c\u0627\u0626\u06cc\u06ba \u062a\u0648 \u0648\u06c1 \u0645\u06a9\u0645\u0644 \u0637\u0648\u0631 \u067e\u0631 \u067e\u0648\u0634\u06cc\u062f\u06c1 \u06c1\u06cc\u06ba\u06d4<\/p>\n<pre><code class=\"language-dart\">testGoldens('task screen in dark mode', (tester) async {\n  final repository = MockTaskRepository();\n  when(() => repository.fetchTasks()).thenAnswer(\n    (_) async => [const Task(id: '1', title: 'Buy milk')],\n  );\n\n  await tester.pumpWidgetBuilder(\n    TaskScreen(notifier: TaskNotifier(repository)),\n    wrapper: materialAppWrapper(theme: ThemeData.dark()),\n  );\n  await tester.pumpAndSettle();\n\n  await screenMatchesGolden(tester, 'task_screen_dark_mode');\n});\n<\/code><\/pre>\n<h2 id=\"heading-keeping-goldens-from-becoming-a-maintenance-burden\">\u0627\u067e\u0646\u06d2 \u06af\u0648\u0644\u0688\u0646 \u06a9\u0648 \u062f\u06cc\u06a9\u06be \u0628\u06be\u0627\u0644 \u06a9\u0627 \u0628\u0648\u062c\u06be \u0628\u0646\u0646\u06d2 \u0633\u06d2 \u0631\u0648\u06a9\u06cc\u06ba\u06d4<\/h2>\n<p>\u0645\u06cc\u06ba \u0646\u06d2 \u062c\u0648 \u0646\u0627\u06a9\u0627\u0645\u06cc \u06a9\u0627 \u0645\u0648\u0688 \u062f\u06cc\u06a9\u06be\u0627 \u06c1\u06d2 \u0648\u06c1 \u0648\u06c1 \u06c1\u06d2 \u062c\u06c1\u0627\u06ba \u0627\u06cc\u06a9 \u0633\u06d2 \u0632\u06cc\u0627\u062f\u06c1 \u0679\u06cc\u0645\u06cc\u06ba \u0627\u06cc\u06a9 \u0645\u06c1\u06cc\u0646\u06d2 \u06a9\u06d2 \u0644\u06cc\u06d2 \u0633\u0646\u06c1\u0631\u06cc \u0631\u0646\u06af \u06a9\u0627 \u0627\u0636\u0627\u0641\u06c1 \u06a9\u0631\u062a\u06cc \u06c1\u06cc\u06ba \u0627\u0648\u0631 \u067e\u06be\u0631 \u0627\u06cc\u06a9 \u062c\u0627\u0626\u0632 \u0688\u06cc\u0632\u0627\u0626\u0646 \u06a9\u06cc \u062a\u0628\u062f\u06cc\u0644\u06cc 15 \u0627\u0633\u06a9\u0631\u06cc\u0646\u0648\u06ba \u067e\u0631 \u0627\u0633\u062a\u0639\u0645\u0627\u0644 \u06c1\u0648\u0646\u06d2 \u0648\u0627\u0644\u06d2 \u0645\u0634\u062a\u0631\u06a9\u06c1 \u062c\u0632\u0648 \u06a9\u0648 \u0645\u062a\u0627\u062b\u0631 \u06a9\u0631\u062a\u06cc \u06c1\u06d2\u06d4 \u067e\u06be\u0631 \u062a\u0645\u0627\u0645 15 \u06af\u0648\u0644\u0688\u0646 \u0679\u06cc\u0633\u0679 \u0628\u06cc\u06a9 \u0648\u0642\u062a \u0646\u0627\u06a9\u0627\u0645 \u06c1\u0648 \u062c\u0627\u062a\u06d2 \u06c1\u06cc\u06ba \u0627\u0648\u0631 \u0679\u06cc\u0645 \u0631\u0646\u0632 \u0628\u0646\u0627\u062a\u06cc \u06c1\u06d2\u06d4 <code>--update-goldens<\/code> \u0627\u0635\u0644 \u0645\u06cc\u06ba \u06c1\u0631 \u0641\u0631\u0642 \u06a9\u06cc \u062c\u0627\u0646\u0686 \u06a9\u06cc\u06d2 \u0628\u063a\u06cc\u0631\u06d4 \u0622\u062e\u0631 \u0645\u06cc\u06ba\u060c \u0627\u0646\u0641\u0631\u0627\u062f\u06cc \u0637\u0648\u0631 \u067e\u0631 15 \u062a\u0635\u0648\u06cc\u0631\u06cc \u0641\u0631\u0642\u0648\u06ba \u0633\u06d2 \u06af\u0632\u0631\u0646\u0627 \u0627\u06cc\u0633\u0627 \u0645\u062d\u0633\u0648\u0633 \u0646\u06c1\u06cc\u06ba \u06a9\u0631\u062a\u0627 \u06a9\u06c1 \u06cc\u06c1 \u0622\u067e \u06a9\u06d2 \u0648\u0642\u062a \u06a9\u06d2 \u0642\u0627\u0628\u0644 \u06c1\u06d2\u06d4<\/p>\n<p>\u0627\u0633 \u0644\u0645\u062d\u06d2 \u0633\u06d2\u060c \u0633\u0646\u06c1\u0631\u06cc \u0627\u0645\u062a\u062d\u0627\u0646 \u0622\u067e \u06a9\u06cc \u062d\u0641\u0627\u0638\u062a \u06a9\u0631\u0646\u0627 \u0686\u06be\u0648\u0691 \u062f\u06cc\u062a\u0627 \u06c1\u06d2\u06d4 \u06a9\u06cc\u0648\u0646\u06a9\u06c1 \u0627\u0633 \u06a9\u06d2 \u0628\u0639\u062f \u0633\u06d2\u060c \u0679\u06cc\u0645 \u06a9\u0627 \u0627\u0636\u0637\u0631\u0627\u0628 &quot;\u06a9\u06be\u06cc\u0644\u0646\u0627 \u0627\u0648\u0631 \u0622\u06af\u06d2 \u0628\u0691\u06be\u0646\u0627&#8221; \u06c1\u06d2 \u0628\u062c\u0627\u0626\u06d2 \u0627\u0633 \u06a9\u06d2 \u06a9\u06c1 &quot;\u06a9\u06cc\u0627 \u0628\u062f\u0644\u0627 \u06c1\u06d2 \u0627\u0648\u0631 \u062f\u06cc\u06a9\u06be\u06cc\u06ba \u06a9\u06c1 \u06a9\u06cc\u0627 \u06cc\u06c1 \u062c\u0627\u0646 \u0628\u0648\u062c\u06be \u06a9\u0631 \u06c1\u06d2\u06d4&#8221;<\/p>\n<p>\u062f\u0648 \u0686\u06cc\u0632\u06cc\u06ba \u0627\u06cc\u0633\u0627 \u06c1\u0648\u0646\u06d2 \u0633\u06d2 \u0631\u0648\u06a9\u062a\u06cc \u06c1\u06cc\u06ba\u06d4 \u0633\u0628 \u0633\u06d2 \u067e\u06c1\u0644\u06d2\u060c \u0627\u067e\u0646\u06d2 \u0633\u0646\u06c1\u0631\u06cc \u0633\u06cc\u0679 \u06a9\u0648 \u0686\u06be\u0648\u0679\u0627 \u0631\u06a9\u06be\u06cc\u06ba \u0627\u0648\u0631 \u0627\u0633\u06d2 \u062e\u0627\u0635 \u0637\u0648\u0631 \u067e\u0631 \u0645\u0646\u062a\u062e\u0628 \u06a9\u0631\u06cc\u06ba\u06d4 \u0645\u06cc\u06ba \u0646\u06d2 \u0627\u0648\u067e\u0631 \u0627\u0633 \u06a9\u0627 \u062a\u0630\u06a9\u0631\u06c1 \u06a9\u06cc\u0627 \u06c1\u06d2\u060c \u0644\u06cc\u06a9\u0646 \u06cc\u06c1 \u062f\u06c1\u0631\u0627\u0646\u06d2 \u06a9\u06d2 \u0644\u06cc\u06d2 \u06a9\u0627\u0641\u06cc \u0636\u0631\u0648\u0631\u06cc \u06c1\u06d2\u06d4 5 \u06cc\u0627 6 \u06c1\u0627\u0626\u06cc \u0648\u06cc\u0644\u06cc\u0648 \u0627\u0633\u06a9\u0631\u06cc\u0646\u0632 \u06a9\u0627 \u0627\u0646\u062a\u062e\u0627\u0628 \u06a9\u0631\u06cc\u06ba\u060c 50 \u0646\u06c1\u06cc\u06ba\u06d4<\/p>\n<p>\u062f\u0648\u0633\u0631\u0627\u060c \u06a9\u0633\u06cc \u0628\u0627\u06a9\u0633 \u06a9\u0648 \u063a\u06cc\u0631 \u0686\u06cc\u06a9 \u06a9\u0631\u0646\u06d2 \u06a9\u06d2 \u0628\u062c\u0627\u0626\u06d2\u060c \u0627\u0635\u0644 \u0645\u06cc\u06ba \u0641\u0631\u0642 \u06a9\u0648 \u06a9\u06be\u0648\u0644\u0646\u06d2 \u06a9\u06d2 \u0644\u06cc\u06d2 \u0633\u0646\u06c1\u0631\u06cc \u0646\u0627\u06a9\u0627\u0645\u06cc\u0648\u06ba \u06a9\u06d2 \u0633\u0644\u0633\u0644\u06d2 \u06a9\u0648 \u0627\u06cc\u06a9 \u0633\u06af\u0646\u0644 \u06a9\u06d2 \u0637\u0648\u0631 \u067e\u0631 \u0633\u0645\u062c\u06be\u06cc\u06ba\u06d4 \u06af\u0648\u0644\u0688\u0646 \u0679\u06cc\u0633\u0679\u0646\u06af \u06a9\u06d2 \u0644\u06cc\u06d2 \u0632\u06cc\u0627\u062f\u06c1 \u062a\u0631 CI \u0633\u06cc\u0679 \u0627\u067e \u062e\u0627\u0635 \u0637\u0648\u0631 \u067e\u0631 \u0645\u062e\u062a\u0644\u0641 \u062a\u0635\u0627\u0648\u06cc\u0631 \u06a9\u0648 \u062a\u0639\u0645\u06cc\u0631\u0627\u062a\u06cc \u0646\u0645\u0648\u0646\u0648\u06ba \u06a9\u06d2 \u0637\u0648\u0631 \u067e\u0631 \u0627\u067e \u0644\u0648\u0688 \u06a9\u0631\u0646\u06d2 \u06a9\u06cc \u0627\u062c\u0627\u0632\u062a \u062f\u06cc\u062a\u06d2 \u06c1\u06cc\u06ba\u060c \u0644\u06c1\u0630\u0627 \u062c\u0627\u0626\u0632\u06c1 \u0644\u06cc\u0646\u06d2 \u0648\u0627\u0644\u06d2 \u0627\u0646 \u062a\u0635\u0627\u0648\u06cc\u0631 \u06a9\u0648 \u0645\u0642\u0627\u0645\u06cc \u0637\u0648\u0631 \u067e\u0631 \u0628\u0631\u0627\u0646\u0686 \u06a9\u0648 \u06a9\u06be\u06cc\u0646\u0686\u06d2 \u0628\u063a\u06cc\u0631 \u067e\u0644 \u06a9\u06cc \u062f\u0631\u062e\u0648\u0627\u0633\u062a \u0645\u06cc\u06ba \u062f\u06cc\u06a9\u06be \u0633\u06a9\u062a\u06d2 \u06c1\u06cc\u06ba\u06d4<\/p>\n<h2 id=\"heading-integration-tests-the-whole-app-end-to-end\">\u0627\u0646\u0679\u06cc\u06af\u0631\u06cc\u0634\u0646 \u0679\u06cc\u0633\u0679\u0646\u06af: \u067e\u0648\u0631\u06cc \u0627\u06cc\u067e\u060c \u0627\u06cc\u0646\u0688 \u0679\u0648 \u0627\u06cc\u0646\u0688<\/h2>\n<p>\u06cc\u0648\u0646\u0679 \u0627\u0648\u0631 \u0648\u06cc\u062c\u06cc\u0679 \u0679\u06cc\u0633\u0679 \u0646\u0642\u0644\u06cc \u0688\u0627\u0631\u0679 \u0645\u0627\u062d\u0648\u0644 \u0645\u06cc\u06ba \u0686\u0644\u0627\u0626\u06d2 \u062c\u0627\u062a\u06d2 \u06c1\u06cc\u06ba\u06d4 \u06a9\u0648\u0626\u06cc \u062d\u0642\u06cc\u0642\u06cc \u0631\u06cc\u0646\u0688\u0631\u0646\u06af \u0627\u0646\u062c\u0646 \u06cc\u0627 \u067e\u0644\u06cc\u0679 \u0641\u0627\u0631\u0645 \u0686\u06cc\u0646\u0644 \u0646\u06c1\u06cc\u06ba \u06c1\u06d2\u060c \u0627\u06cc\u06a9 \u062c\u0639\u0644\u06cc \u0630\u062e\u06cc\u0631\u06c1 \u0646\u06cc\u0679 \u0648\u0631\u06a9 \u067e\u0631 \u0642\u0628\u0636\u06c1 \u06a9\u0631 \u0644\u06cc\u062a\u0627 \u06c1\u06d2\u06d4 \u06cc\u06c1\u06cc \u0686\u06cc\u0632 \u0627\u0646\u06c1\u06cc\u06ba \u062a\u06cc\u0632 \u062a\u0631 \u0628\u0646\u0627\u062a\u06cc \u06c1\u06d2\u060c \u0627\u0648\u0631 \u06cc\u06c1\u06cc \u0686\u06cc\u0632 \u0627\u0646\u06c1\u06cc\u06ba \u0645\u0636\u062d\u06a9\u06c1 \u062e\u06cc\u0632 \u0628\u0646\u0627\u062a\u06cc \u06c1\u06d2\u06d4 \u06cc\u0639\u0646\u06cc\u060c \u0686\u0627\u06c1\u06d2 \u0627\u06cc\u06a9 \u062d\u0642\u06cc\u0642\u06cc \u0627\u06cc\u067e \u0645\u0631\u062a\u0628 \u06a9\u06cc \u06af\u0626\u06cc \u06c1\u0648 \u0627\u0648\u0631 \u0627\u06cc\u06a9 \u062d\u0642\u06cc\u0642\u06cc \u0688\u06cc\u0648\u0627\u0626\u0633 \u06cc\u0627 \u0627\u06cc\u0645\u0648\u0644\u06cc\u0679\u0631 \u067e\u0631 \u0686\u0644 \u0631\u06c1\u06cc \u06c1\u0648\u060c \u0627\u0635\u0644 \u0645\u06cc\u06ba \u0627\u0633 \u0648\u0642\u062a \u06a9\u0627\u0645 \u06a9\u0631\u062a\u06cc \u06c1\u06d2 \u062c\u0628 \u062a\u0645\u0627\u0645 \u067e\u0631\u062a\u06cc\u06ba \u0627\u06cc\u06a9 \u0633\u0627\u062a\u06be \u062c\u0691\u06cc \u06c1\u0648\u06ba\u06d4<\/p>\n<pre><code class=\"language-yaml\">dev_dependencies:\n  integration_test:\n    sdk: flutter\n<\/code><\/pre>\n<pre><code class=\"language-dart\">\/\/ integration_test\/complete_task_test.dart\nimport 'package:flutter\/material.dart';\nimport 'package:flutter_test\/flutter_test.dart';\nimport 'package:integration_test\/integration_test.dart';\nimport 'package:my_app\/main.dart' as app;\n\nvoid main() {\n  IntegrationTestWidgetsFlutterBinding.ensureInitialized();\n\n  testWidgets('user can load tasks and complete one, end to end', (tester) async {\n    \/\/ This runs your actual main() \u2014 the real app, the real\n    \/\/ repository implementation, whatever backend it's wired to\n    \/\/ in this build (typically a staging environment for CI).\n    app.main();\n    await tester.pumpAndSettle();\n\n    expect(find.text('Buy milk'), findsOneWidget);\n    expect(find.textContaining('0 done'), findsOneWidget);\n\n    await tester.tap(find.byType(CheckboxListTile).first);\n    await tester.pumpAndSettle();\n\n    expect(find.textContaining('1 done'), findsOneWidget);\n  });\n}\n<\/code><\/pre>\n<p>\u0627\u0633\u06d2 \u0627\u0635\u0644\u06cc \u0688\u06cc\u0648\u0627\u0626\u0633 \u06cc\u0627 \u0627\u06cc\u0645\u0648\u0644\u06cc\u0679\u0631 \u06a9\u06d2 \u062e\u0644\u0627\u0641 \u0686\u0644\u0627\u0626\u06cc\u06ba\u06d4<\/p>\n<pre><code class=\"language-bash\">flutter test integration_test\/complete_task_test.dart\n<\/code><\/pre>\n<p>\u06cc\u06c1 \u0633\u0633\u062a \u06c1\u06d2 (\u0645\u0644\u06cc \u0633\u06cc\u06a9\u0646\u0688 \u06a9\u06d2 \u0628\u062c\u0627\u0626\u06d2 \u0633\u06cc\u06a9\u0646\u0688) \u06a9\u06cc\u0648\u0646\u06a9\u06c1 \u06cc\u06c1 \u0645\u0635\u0646\u0648\u0639\u06cc \u0648\u06cc\u062c\u06cc\u0679 \u0679\u0631\u06cc \u06a9\u06d2 \u0628\u062c\u0627\u0626\u06d2 \u0627\u0635\u0644 \u0627\u06cc\u067e \u06a9\u0648 \u0645\u0631\u062a\u0628 \u0627\u0648\u0631 \u0686\u0644\u0627\u062a\u0627 \u06c1\u06d2\u06d4 \u0627\u0646 \u0627\u062e\u0631\u0627\u062c\u0627\u062a \u06a9\u06cc \u0648\u062c\u06c1 \u0633\u06d2\u060c \u0627\u0646\u0636\u0645\u0627\u0645 \u06a9\u06d2 \u0679\u06cc\u0633\u0679 \u0645\u06cc\u06ba \u06c1\u0631 \u0627\u0633\u06a9\u0631\u06cc\u0646 \u06a9\u06d2 \u0628\u062c\u0627\u0626\u06d2 \u0628\u06c1\u062a \u06a9\u0645 \u062a\u0639\u062f\u0627\u062f \u0645\u06cc\u06ba \u0628\u06c1\u0627\u0624 \u06a9\u0627 \u0627\u062d\u0627\u0637\u06c1 \u06a9\u0631\u0646\u0627 \u0686\u0627\u06c1\u06cc\u06d2 \u062c\u0648 \u062f\u0631\u062d\u0642\u06cc\u0642\u062a \u0646\u0642\u0635\u0627\u0646 \u06a9\u0627 \u0628\u0627\u0639\u062b \u0628\u0646 \u0633\u06a9\u062a\u06d2 \u06c1\u06cc\u06ba\u060c \u062c\u06cc\u0633\u06d2 \u06a9\u06c1 \u062e\u0631\u06cc\u062f\u0627\u0631\u06cc \u0645\u06a9\u0645\u0644 \u06a9\u0631\u0646\u0627 \u06cc\u0627 \u0644\u0627\u06af \u0627\u0646 \u06a9\u0631\u0646\u0627 (\u06cc\u0639\u0646\u06cc \u0628\u0646\u06cc\u0627\u062f\u06cc \u06a9\u0627\u0645 \u062c\u0648 \u0627\u06cc\u067e \u06a9\u0633\u06cc \u06a9\u0648 \u06a9\u0631\u0646\u06d2 \u06a9\u06cc \u0627\u062c\u0627\u0632\u062a \u062f\u06cc\u0646\u06d2 \u06a9\u06d2 \u0644\u06cc\u06d2 \u0645\u0648\u062c\u0648\u062f \u06c1\u06d2) \u06c1\u0631 \u0627\u0633\u06a9\u0631\u06cc\u0646 \u06a9\u06d2 \u0628\u062c\u0627\u0626\u06d2\u06d4 \u0645\u06cc\u06ba \u0627\u0646 \u0645\u06cc\u06ba \u0633\u06d2 5 \u06cc\u0627 6 \u06a9\u0648 \u062d\u0642\u06cc\u0642\u06cc \u067e\u0631\u0648\u062c\u06cc\u06a9\u0679\u0633 \u0645\u06cc\u06ba \u0686\u0644\u0627\u062a\u0627 \u06c1\u0648\u06ba \u0627\u0648\u0631 \u0648\u06c1 \u0627\u0633 \u0628\u06c1\u0627\u0624 \u06a9\u0627 \u0627\u062d\u0627\u0637\u06c1 \u06a9\u0631\u062a\u06d2 \u06c1\u06cc\u06ba \u062c\u0648 \u0645\u06cc\u06ba \u0627\u067e\u0646\u06d2 \u0635\u0627\u0631\u0641\u06cc\u0646 \u0633\u06d2 \u067e\u06c1\u0644\u06d2 \u062c\u0627\u0646\u0646\u0627 \u0686\u0627\u06c1\u062a\u0627 \u06c1\u0648\u06ba\u06d4<\/p>\n<h2 id=\"heading-flakiness-retries-and-real-devices\">\u0639\u062f\u0645 \u0627\u0633\u062a\u062d\u06a9\u0627\u0645\u060c \u062f\u0648\u0628\u0627\u0631\u06c1 \u06a9\u0648\u0634\u0634\u06cc\u06ba\u060c \u0627\u0648\u0631 \u062d\u0642\u06cc\u0642\u06cc \u0622\u0644\u0627\u062a<\/h2>\n<p>\u0627\u0646\u0679\u06cc\u06af\u0631\u06cc\u0634\u0646 \u0679\u06cc\u0633\u0679 \u0627\u0633 \u0637\u0631\u062d \u0646\u0627\u06a9\u0627\u0645 \u06c1\u0648 \u062c\u0627\u062a\u06d2 \u06c1\u06cc\u06ba \u062c\u0633 \u0637\u0631\u062d \u062f\u06cc\u06af\u0631 \u062a\u06cc\u0646 \u0627\u0642\u0633\u0627\u0645 \u0645\u06cc\u06ba \u0633\u06d2 \u0627\u06a9\u062b\u0631 \u0646\u0627\u06a9\u0627\u0645 \u06c1\u0648 \u062c\u0627\u062a\u06d2 \u06c1\u06cc\u06ba: \u06cc\u0639\u0646\u06cc\u060c \u06cc\u06c1 \u06a9\u06cc\u0691\u06d2 \u0633\u06d2 \u063a\u06cc\u0631 \u0645\u062a\u0639\u0644\u0642 \u0648\u062c\u0648\u06c1\u0627\u062a \u06a9\u06cc \u0628\u0646\u0627 \u067e\u0631 \u0648\u0642\u0641\u06d2 \u0648\u0642\u0641\u06d2 \u0633\u06d2 \u0646\u0627\u06a9\u0627\u0645 \u06c1\u0648 \u062c\u0627\u062a\u0627 \u06c1\u06d2\u06d4 \u0627\u06cc\u06a9 CI \u0627\u06cc\u0645\u0648\u0644\u06cc\u0679\u0631 \u0645\u0639\u0645\u0648\u0644 \u0633\u06d2 \u0632\u06cc\u0627\u062f\u06c1 \u0622\u06c1\u0633\u062a\u06c1 \u0686\u0644 \u0631\u06c1\u0627 \u06c1\u06d2\u060c \u0633\u0679\u06cc\u062c\u0646\u06af \u0645\u0627\u062d\u0648\u0644 \u067e\u0631 \u0646\u06cc\u0679 \u0648\u0631\u06a9 \u06a9\u0627\u0644 \u062c\u0633 \u0645\u06cc\u06ba \u0679\u06cc\u0633\u0679 \u06a9\u06cc \u062a\u0648\u0642\u0639 \u0633\u06d2 \u0622\u062f\u06be\u0627 \u0633\u06cc\u06a9\u0646\u0688 \u0632\u06cc\u0627\u062f\u06c1 \u0648\u0642\u062a \u0644\u06af\u062a\u0627 \u06c1\u06d2\u060c \u0627\u06af\u0644\u0627 \u0679\u0627\u0633\u06a9 \u0686\u0644\u0646\u06d2 \u067e\u0631 \u0627\u06cc\u0646\u06cc\u0645\u06cc\u0634\u0646\u0632 \u0627\u0628\u06be\u06cc \u0628\u06be\u06cc \u0637\u06d2 \u0646\u06c1\u06cc\u06ba \u06c1\u0648\u062a\u06cc \u06c1\u06cc\u06ba\u060c \u0648\u063a\u06cc\u0631\u06c1\u06d4 \u06cc\u06c1 \u0633\u0628 \u0627\u06cc\u0633\u06cc \u062e\u0631\u0627\u0628\u06cc\u0627\u06ba \u067e\u06cc\u062f\u0627 \u06a9\u0631\u062a\u06d2 \u06c1\u06cc\u06ba \u062c\u0646 \u06a9\u0627 \u0627\u0633 \u0633\u06d2 \u06a9\u0648\u0626\u06cc \u062a\u0639\u0644\u0642 \u0646\u06c1\u06cc\u06ba \u06c1\u06d2 \u06a9\u06c1 \u0622\u06cc\u0627 \u0627\u06cc\u067e \u0648\u0627\u0642\u0639\u06cc \u06a9\u0627\u0645 \u06a9\u0631\u062a\u06cc \u06c1\u06d2\u06d4<\/p>\n<p>\u0627\u06cc\u06a9 \u0639\u0627\u062f\u062a \u062c\u0633 \u0646\u06d2 \u0645\u062c\u06be\u06d2 \u0633\u0628 \u0633\u06d2 \u0632\u06cc\u0627\u062f\u06c1 \u0645\u0627\u06cc\u0648\u0633 \u06a9\u06cc\u0627 \u06c1\u06d2 \u0648\u06c1 \u0632\u0646\u062c\u06cc\u0631 \u0646\u06c1 \u0628\u0627\u0646\u062f\u06be\u0646\u0627 \u06c1\u06d2\u06d4 <code>tester.tap()<\/code> \u0628\u0631\u0627\u06c1 \u0631\u0627\u0633\u062a \u06a9\u0633\u06cc \u062f\u0648\u0633\u0631\u06d2 \u062a\u0639\u0627\u0645\u0644 \u06a9\u06d2 \u0628\u063a\u06cc\u0631 <code>pumpAndSettle()<\/code> (\u06cc\u0627 \u0648\u0627\u0636\u062d <code>pump(duration)<\/code>) \u062f\u0631\u06cc\u06ba \u0627\u062b\u0646\u0627\u060c \u06cc\u06c1\u0627\u06ba \u062a\u06a9 \u06a9\u06c1 \u062c\u0628 \u06cc\u06c1 \u0628\u06d2 \u06a9\u0627\u0631 \u0645\u062d\u0633\u0648\u0633 \u06c1\u0648\u062a\u0627 \u06c1\u06d2\u06d4<\/p>\n<pre><code class=\"language-dart\">\/\/ Flaky: if the tap triggers any async work (a network call, an\n\/\/ animation), the next find() can run before it resolves,\n\/\/ and the test fails unpredictably depending on machine speed.\nawait tester.tap(find.byType(CheckboxListTile).first);\nexpect(find.textContaining('1 done'), findsOneWidget);\n\n\/\/ Reliable: explicitly wait for everything triggered by the tap\n\/\/ to finish before asserting on the result.\nawait tester.tap(find.byType(CheckboxListTile).first);\nawait tester.pumpAndSettle();\nexpect(find.textContaining('1 done'), findsOneWidget);\n<\/code><\/pre>\n<p>\u062e\u0627\u0635 \u0637\u0648\u0631 \u067e\u0631 CI \u06a9\u06d2 \u0644\u06cc\u06d2\u060c \u062d\u0642\u06cc\u0642\u06cc \u0688\u06cc\u0648\u0627\u0626\u0633 \u0641\u0627\u0631\u0645 \u06a9\u06d2 \u062e\u0644\u0627\u0641 \u0627\u0646\u0679\u06cc\u06af\u0631\u06cc\u0634\u0646 \u0679\u06cc\u0633\u0679 \u0686\u0644\u0627\u0646\u0627 (Firebase Test Lab \u06cc\u0627 CI executor \u0633\u06d2 \u062c\u0691\u06d2 \u06c1\u0648\u0626\u06d2 \u062d\u0642\u06cc\u0642\u06cc \u0622\u0644\u0627\u062a) \u06a9\u06cc\u0679\u06af\u0631\u06cc\u0632 \u06a9\u06cc \u062e\u0631\u0627\u0628\u06cc\u0648\u06ba \u06a9\u0648 \u067e\u06a9\u0691\u062a\u0627 \u06c1\u06d2 \u062c\u0646\u06c1\u06cc\u06ba \u0627\u06cc\u0645\u0648\u0644\u06cc\u0679\u0631 \u06a9\u0628\u06be\u06cc \u06a9\u0628\u06be\u06cc \u0645\u06a9\u0645\u0644 \u0637\u0648\u0631 \u067e\u0631 \u06a9\u06be\u0648 \u0633\u06a9\u062a\u06d2 \u06c1\u06cc\u06ba: \u0627\u062c\u0627\u0632\u062a \u06a9\u06d2 \u0688\u0627\u0626\u06cc\u0644\u0627\u06af \u062c\u0648 \u0645\u062e\u062a\u0644\u0641 \u0637\u0631\u06cc\u0642\u06d2 \u0633\u06d2 \u0628\u0631\u062a\u0627\u0624 \u06a9\u0631\u062a\u06d2 \u06c1\u06cc\u06ba\u060c \u06a9\u06cc\u0645\u0631\u06c1 \u06cc\u0627 \u0628\u0627\u0626\u06cc\u0648 \u0645\u06cc\u0679\u0631\u06a9 \u067e\u0631\u0627\u0645\u067e\u0679\u0633\u060c \u06a9\u0645 \u0645\u06cc\u0645\u0648\u0631\u06cc \u062c\u0648 \u0635\u0631\u0641 \u062d\u0642\u06cc\u0642\u06cc \u06c1\u0627\u0631\u0688 \u0648\u06cc\u0626\u0631 \u067e\u0631 \u0638\u0627\u06c1\u0631 \u06c1\u0648\u062a\u06cc \u06c1\u06d2\u060c \u06c1\u0631 \u0631\u0627\u062a \u06a9\u0648 \u0631\u06cc\u0644\u06cc\u0632 \u06a9\u0631\u0646\u06d2 \u0633\u06d2 \u067e\u06c1\u0644\u06d2\u060c \u0648\u063a\u06cc\u0631\u06c1\u06d4 \u06a9\u06cc\u0648\u0646\u06a9\u06c1 \u06cc\u06c1 \u0633\u0628 \u0633\u06d2 \u0645\u06c1\u0646\u06af\u0627 \u0627\u0648\u0631 \u0633\u0633\u062a \u062a\u0631\u06cc\u0646 \u0622\u067e\u0634\u0646 \u06c1\u06d2\u06d4<\/p>\n<p>\u0627\u06af\u0631 \u0622\u067e \u06a9\u06cc \u0627\u06cc\u067e \u0627\u062a\u0646\u06cc \u067e\u06cc\u0686\u06cc\u062f\u06c1 \u06c1\u06d2 \u06a9\u06c1 \u0628\u06c1\u062a\u0631 \u0645\u0631\u0628\u0648\u0637 \u0679\u06cc\u0633\u0679 \u0679\u0648\u0644\u0632 \u06a9\u06cc \u0636\u0645\u0627\u0646\u062a \u062f\u06d2 \u0633\u06a9\u06d2 (\u0628\u0646\u06cc\u0627\u062f\u06cc \u0627\u062c\u0627\u0632\u062a\u0648\u06ba \u06a9\u0648 \u0633\u0646\u0628\u06be\u0627\u0644\u0646\u0627\u060c \u0628\u0627\u0626\u06cc\u0648 \u0645\u06cc\u0679\u0631\u06a9\u0633 \u06a9\u0627 \u0645\u0630\u0627\u0642 \u0627\u0691\u0627\u0646\u0627\u060c \u06cc\u0627 \u067e\u0644\u06cc\u0679 \u0641\u0627\u0631\u0645 \u06a9\u06d2 \u06af\u06c1\u0631\u06d2 \u062a\u0639\u0627\u0645\u0644\u0627\u062a) <code>patrol<\/code> \u06cc\u06c1 \u062f\u06cc\u06a9\u06be\u0646\u06d2 \u06a9\u06d2 \u0642\u0627\u0628\u0644 \u06c1\u06d2\u06d4 \u0627\u0633 \u067e\u0631 \u0645\u0628\u0646\u06cc \u06c1\u06d2\u06d4 <code>integration_test<\/code> \u062a\u0627\u06c1\u0645\u060c \u06cc\u06c1 \u0648\u06c1 \u062e\u0635\u0648\u0635\u06cc\u0627\u062a \u0634\u0627\u0645\u0644 \u06a9\u0631\u062a\u0627 \u06c1\u06d2 \u062c\u0648 \u0628\u06cc\u0633 \u067e\u06cc\u06a9\u062c \u0645\u06cc\u06ba \u0646\u06c1\u06cc\u06ba \u067e\u0627\u0626\u06cc \u062c\u0627\u062a\u06cc \u06c1\u06cc\u06ba\u06d4<\/p>\n<h2 id=\"heading-where-each-test-type-actually-pays-off\">\u062c\u06c1\u0627\u06ba \u06c1\u0631 \u0679\u06cc\u0633\u0679 \u06a9\u06cc \u0642\u0633\u0645 \u0648\u0627\u0642\u0639\u06cc \u0627\u062f\u0627\u0626\u06cc\u06af\u06cc \u06a9\u0631\u062a\u06cc \u06c1\u06d2\u06d4<\/h2>\n<p>\u0627\u0633 \u0686\u0627\u0631 \u0679\u0627\u0626\u0631\u0688 \u0627\u067e\u0631\u0648\u0686 \u06a9\u06d2 \u0633\u0627\u062a\u06be \u0645\u062a\u0639\u062f\u062f \u0627\u06cc\u067e\u0633 \u0644\u0627\u0646\u0686 \u06a9\u0631\u0646\u06d2 \u06a9\u06d2 \u0628\u0639\u062f\u060c \u06cc\u06c1\u0627\u06ba \u062a\u0642\u0631\u06cc\u0628\u0627\u064b \u06cc\u06c1 \u06c1\u06d2 \u06a9\u06c1 \u06a9\u0633 \u0637\u0631\u062d \u0627\u0648\u0631 \u06a9\u06cc\u0648\u06ba \u06a9\u0648\u0634\u0634\u06cc\u06ba \u0645\u062e\u062a\u0635 \u06a9\u06cc \u062c\u0627\u0626\u06cc\u06ba:<\/p>\n<p><strong>\u06cc\u0648\u0646\u0679 \u0679\u06cc\u0633\u0679\u0646\u06af \u0641\u0631\u0627\u062e\u062f\u0644\u06cc \u0633\u06d2 \u06a9\u06cc \u062c\u0627\u062a\u06cc \u06c1\u06d2\u06d4<\/strong> \u0622\u067e \u0627\u0633\u06d2 \u062a\u0642\u0631\u06cc\u0628\u0627\u064b \u0622\u0632\u0627\u062f\u0627\u0646\u06c1 \u0637\u0648\u0631 \u067e\u0631 \u0644\u06a9\u06be \u0627\u0648\u0631 \u0686\u0644\u0627 \u0633\u06a9\u062a\u06d2 \u06c1\u06cc\u06ba\u060c \u0627\u0648\u0631 \u06cc\u06c1 \u0648\u0627\u062d\u062f \u067e\u0631\u062a \u06c1\u06d2 \u062c\u0648 \u0645\u0646\u0637\u0642\u06cc \u06a9\u06cc\u0691\u06d2 \u0628\u0635\u0631\u06cc \u0637\u0648\u0631 \u067e\u0631 \u0638\u0627\u06c1\u0631 \u06c1\u0648\u0646\u06d2 \u0633\u06d2 \u067e\u06c1\u0644\u06d2 \u067e\u06a9\u0691\u062a\u06cc \u06c1\u06d2\u06d4 \u0642\u06cc\u0645\u062a \u06a9\u06d2 \u062a\u0645\u0627\u0645 \u063a\u06cc\u0631 \u0645\u0639\u0645\u0648\u0644\u06cc \u062d\u0633\u0627\u0628\u0627\u062a\u060c \u0641\u0644\u0679\u0631\u0632 \u0627\u0648\u0631 \u06a9\u0627\u0631\u0648\u0628\u0627\u0631\u06cc \u0645\u0646\u0637\u0642 \u0627\u06cc\u06a9 \u062d\u0627\u0635\u0644 \u06a9\u0631\u062a\u06d2 \u06c1\u06cc\u06ba\u06d4<\/p>\n<p><strong>\u0627\u0646 \u062a\u0645\u0627\u0645 \u0627\u0633\u06a9\u0631\u06cc\u0646\u0648\u06ba \u067e\u0631 \u0648\u06cc\u062c\u06cc\u0679\u0633 \u06a9\u06cc \u062c\u0627\u0646\u0686 \u06a9\u0631\u06cc\u06ba \u062c\u0646 \u06a9\u06cc \u0627\u06cc\u06a9 \u0633\u06d2 \u0632\u06cc\u0627\u062f\u06c1 \u062d\u0627\u0644\u062a \u06c1\u06d2\u06d4<\/strong> \u0644\u0648\u0688\u0646\u06af\u060c \u063a\u0644\u0637\u06cc\u0627\u06ba\u060c \u0627\u0648\u0631 \u06a9\u0627\u0645\u06cc\u0627\u0628\u06cc \u062a\u06cc\u0646 \u0645\u062e\u062a\u0644\u0641 \u06a9\u0648\u0688 \u0631\u0627\u0633\u062a\u06d2 \u06c1\u06cc\u06ba\u060c \u06c1\u0631 \u0627\u06cc\u06a9 \u06a9\u06cc\u0691\u06d2 \u06a9\u06d2 \u0644\u06cc\u06d2 \u062e\u0627\u0645\u0648\u0634\u06cc \u0633\u06d2 \u0686\u06be\u067e\u0627\u0646\u06d2 \u06a9\u06cc \u062c\u06af\u06c1 \u06c1\u06d2\u06d4 \u0627\u06af\u0631 \u0627\u0633\u06a9\u0631\u06cc\u0646 \u067e\u0631 \u0635\u0631\u0641 \u0627\u06cc\u06a9 \u06c1\u06cc \u062d\u0627\u0644\u062a \u06c1\u06d2 \u062a\u0648\u060c \u0648\u06cc\u062c\u06cc\u0679 \u06a9\u06cc \u062c\u0627\u0646\u0686 \u06a9\u0645 \u0642\u06cc\u0645\u062a \u06a9\u0627 \u0627\u0636\u0627\u0641\u06c1 \u06a9\u0631\u062a\u06cc \u06c1\u06d2\u06d4 \u0627\u06af\u0631 \u0622\u067e \u06a9\u06d2 \u067e\u0627\u0633 3 \u06c1\u06cc\u06ba\u060c \u062a\u0648 \u0627\u0646 \u0645\u06cc\u06ba \u0633\u06d2 2 \u06a9\u0648 \u0686\u06be\u0648\u0691\u0646\u0627 \u0627\u0633\u06a9\u0631\u06cc\u0646 \u067e\u0631 \u0627\u0635\u0644 \u06a9\u0627\u0631\u0631\u0648\u0627\u0626\u06cc \u06a9\u06d2 2\/3 \u06a9\u0648 \u0686\u06be\u0648\u0691\u0646\u06d2 \u06a9\u06d2 \u0645\u062a\u0631\u0627\u062f\u0641 \u06c1\u06d2\u06d4<\/p>\n<p><strong>\u06af\u0648\u0644\u0688\u0646 \u0679\u06cc\u0633\u0679 \u0627\u062d\u062a\u06cc\u0627\u0637 \u0627\u0648\u0631 \u062c\u0627\u0646 \u0628\u0648\u062c\u06be \u06a9\u0631 \u06a9\u06cc\u0627 \u062c\u0627\u062a\u0627 \u06c1\u06d2\u06d4<\/strong> \u0627\u0646 \u0627\u0633\u06a9\u0631\u06cc\u0646\u0648\u06ba \u06a9\u06d2 \u0644\u06cc\u06d2 \u0645\u062e\u0635\u0648\u0635 \u06c1\u06d2 \u062c\u06c1\u0627\u06ba \u0628\u0635\u0631\u06cc \u0631\u062c\u0639\u062a \u0648\u0627\u0642\u0639\u06cc \u0634\u0631\u0645\u0646\u0627\u06a9 \u06c1\u0648 \u0633\u06a9\u062a\u06cc \u06c1\u06d2\u060c \u062c\u06cc\u0633\u06d2 \u0686\u06cc\u06a9 \u0622\u0624\u0679 \u0641\u0644\u0648 \u06cc\u0627 \u06a9\u0648\u0631 \u0627\u0633\u06a9\u0631\u06cc\u0646\u0632 \u062c\u0648 \u0635\u0627\u0631\u0641\u06cc\u0646 \u06c1\u0631 \u0633\u06cc\u0634\u0646 \u0645\u06cc\u06ba \u062f\u06cc\u06a9\u06be\u062a\u06d2 \u06c1\u06cc\u06ba\u06d4 \u0645\u06cc\u06ba \u0627\u0633\u06d2 \u0627\u067e\u0646\u06cc \u0627\u06cc\u067e \u0645\u06cc\u06ba \u06c1\u0631 \u0627\u0633\u06a9\u0631\u06cc\u0646 \u067e\u0631 \u0627\u0633\u062a\u0639\u0645\u0627\u0644 \u0646\u06c1\u06cc\u06ba \u06a9\u0631\u062a\u0627 \u06a9\u06cc\u0648\u0646\u06a9\u06c1 \u062f\u06cc\u06a9\u06be \u0628\u06be\u0627\u0644 \u06a9\u06d2 \u0627\u062e\u0631\u0627\u062c\u0627\u062a \u062d\u0642\u06cc\u0642\u06cc \u06c1\u06cc\u06ba \u0627\u0648\u0631 \u06c1\u0631 \u062a\u0631\u062a\u06cc\u0628 \u06a9\u0648 \u0627\u067e\u0646\u06cc \u062c\u06af\u06c1 \u067e\u0631 \u0644\u0627\u06a9 \u06a9\u0631\u0646\u06d2 \u06a9\u06d2 \u0642\u0627\u0628\u0644 \u0646\u06c1\u06cc\u06ba \u06c1\u06d2\u06d4<\/p>\n<p><strong>\u0645\u062a\u0639\u062f\u062f \u0628\u06c1\u0627\u0624 \u06a9\u06d2 \u0644\u06cc\u06d2 \u0627\u0646\u0679\u06cc\u06af\u0631\u06cc\u0634\u0646 \u0679\u06cc\u0633\u0679 \u062c\u0648 \u0627\u06cc\u067e \u06a9\u06cc \u0648\u0636\u0627\u062d\u062a \u06a9\u0631\u062a\u06d2 \u06c1\u06cc\u06ba\u06d4<\/strong> \u06cc\u06c1 \u062c\u0627\u0645\u0639 \u06a9\u0648\u0631\u06cc\u062c \u0646\u06c1\u06cc\u06ba \u06c1\u06d2\u060c \u0644\u06cc\u06a9\u0646 \u06cc\u06c1 \u062c\u0627\u0646\u0646\u0627 \u06a9\u0627\u0641\u06cc \u06c1\u06d2 \u06a9\u06c1 \u0627\u06cc\u067e \u06a9\u0627 \u0627\u0635\u0644 \u0645\u0642\u0635\u062f \u062a\u0628 \u0628\u06be\u06cc \u06a9\u0627\u0645 \u06a9\u0631\u062a\u0627 \u06c1\u06d2 \u062c\u0628 \u062a\u0645\u0627\u0645 \u0627\u0635\u0644 \u067e\u0631\u062a\u06cc\u06ba \u0627\u06cc\u06a9 \u0633\u0627\u062a\u06be \u0645\u0646\u0633\u0644\u06a9 \u06c1\u0648\u06ba\u06d4<\/p>\n<h2 id=\"heading-mistakes-that-undermine-a-test-suite-slowly\">\u0648\u06c1 \u063a\u0644\u0637\u06cc\u0627\u06ba \u062c\u0648 \u0622\u067e \u06a9\u06d2 \u0679\u06cc\u0633\u0679 \u0633\u0648\u06cc\u0679 \u06a9\u0648 \u0622\u06c1\u0633\u062a\u06c1 \u0622\u06c1\u0633\u062a\u06c1 \u06a9\u0645\u0632\u0648\u0631 \u06a9\u0631 \u0631\u06c1\u06cc \u06c1\u06cc\u06ba\u06d4<\/h2>\n<p>\u0627\u0646 \u0645\u06cc\u06ba \u0633\u06d2 \u06a9\u0648\u0626\u06cc \u0628\u06be\u06cc \u062a\u0639\u0645\u06cc\u0631 \u0641\u0648\u0631\u06cc \u0637\u0648\u0631 \u067e\u0631 \u0646\u06c1\u06cc\u06ba \u0679\u0648\u0679\u06d2 \u06af\u0627\u06d4 \u062c\u0633 \u0637\u0631\u062d \u0627\u06cc\u06a9 \u063a\u06cc\u0631 \u0633\u0627\u062e\u062a\u06c1 \u06a9\u0648\u0688\u0628\u06cc\u0633 \u06c1\u0631 \u0645\u0627\u06c1 \u0627\u06cc\u06a9 \u062f\u0646 \u06a9\u06cc \u0645\u06a9\u0645\u0644 \u0646\u0627\u06a9\u0627\u0645\u06cc \u06a9\u06d2 \u0628\u063a\u06cc\u0631 \u062a\u0628\u062f\u06cc\u0644\u06cc\u0627\u06ba \u06a9\u0631\u0646\u0627 \u0632\u06cc\u0627\u062f\u06c1 \u0645\u0634\u06a9\u0644 \u0628\u0646\u0627\u062a\u0627 \u06c1\u06d2\u060c \u06cc\u06c1 \u0633\u0628 \u0622\u067e \u06a9\u06d2 \u0679\u06cc\u0633\u0679 \u0633\u0648\u06cc\u0679 \u06a9\u0648 \u06a9\u0645 \u0642\u0627\u0628\u0644 \u0627\u0639\u062a\u0645\u0627\u062f \u0628\u0646\u0627 \u062f\u06cc\u062a\u06d2 \u06c1\u06cc\u06ba \u0627\u06af\u0631 \u06c1\u0631 \u0645\u06c1\u06cc\u0646\u06d2 \u06a9\u0686\u06be \u063a\u0644\u0637 \u06c1\u0648 \u062c\u0627\u062a\u0627 \u06c1\u06d2\u06d4<\/p>\n<p>\u067e\u06c1\u0644\u06cc \u063a\u0644\u0637\u06cc \u0627\u0633 \u06a9\u0627 \u0645\u0630\u0627\u0642 \u0627\u0691\u0627\u0646\u0627 \u06c1\u06d2 \u062c\u0633 \u06a9\u06cc \u0622\u067e \u0627\u0635\u0644 \u0645\u06cc\u06ba \u062c\u0627\u0646\u0686 \u06a9\u0631\u0646\u0627 \u0686\u0627\u06c1\u062a\u06d2 \u06c1\u06cc\u06ba\u06d4 \u0645\u06cc\u06ba \u0646\u06d2 \u0630\u062e\u06cc\u0631\u0648\u06ba \u06a9\u06d2 \u0644\u06cc\u06d2 &quot;\u06cc\u0648\u0646\u0679 \u0679\u06cc\u0633\u0679&#8221; \u062f\u06cc\u06a9\u06be\u0627 \u0627\u0648\u0631 \u0644\u06a9\u06be\u0627 \u06c1\u06d2 \u062c\u0648 HTTP \u06a9\u0644\u0627\u0626\u0646\u0679\u0633 \u06a9\u0627 \u0628\u06c1\u062a \u0627\u0686\u06be\u06cc \u0637\u0631\u062d \u0645\u0630\u0627\u0642 \u0627\u0691\u0627\u062a\u06d2 \u06c1\u06cc\u06ba\u06d4 \u0679\u06cc\u0633\u0679 \u062f\u0631\u0627\u0635\u0644 \u06cc\u06c1 \u062b\u0627\u0628\u062a \u06a9\u0631\u0646\u0627 \u062a\u06be\u0627 \u06a9\u06c1 Dio \u06a9\u06d2 \u0627\u067e\u0646\u06d2 \u06a9\u0644\u0627\u0626\u0646\u0679 \u0646\u06d2 \u062c\u06cc\u0633\u0627 \u0633\u0644\u0648\u06a9 \u06a9\u06cc\u0627 \u062c\u06cc\u0633\u0627 \u06a9\u06c1 Dio \u06a9\u06cc \u062f\u0633\u062a\u0627\u0648\u06cc\u0632\u0627\u062a \u0645\u06cc\u06ba \u0628\u06cc\u0627\u0646 \u06a9\u06cc\u0627 \u06af\u06cc\u0627 \u06c1\u06d2\u06d4 \u0627\u06af\u0631 \u0622\u067e \u06a9\u06d2 \u06a9\u0648\u0688 \u0645\u06cc\u06ba \u06a9\u0648\u0626\u06cc \u0627\u0635\u0644 \u0628\u06af \u06c1\u06d2 \u0627\u0648\u0631 \u0679\u06cc\u0633\u0679 \u0646\u0627\u06a9\u0627\u0645 \u0646\u06c1\u06cc\u06ba \u06c1\u0648 \u0633\u06a9\u062a\u0627 \u062a\u0648 \u0622\u067e \u06a9\u0648\u0688 \u06a9\u06cc \u062c\u0627\u0646\u0686 \u0646\u06c1\u06cc\u06ba \u06a9\u0631 \u0631\u06c1\u06d2 \u06c1\u06cc\u06ba\u06d4<\/p>\n<p>\u062f\u0648\u0633\u0631\u0627 \u0646\u0627\u06a9\u0627\u0645\u06cc \u06a9\u06d2 \u0631\u0627\u0633\u062a\u06d2 \u06a9\u0648 \u0686\u06be\u0648\u0691\u0646\u0627 \u06c1\u06d2 \u06a9\u06cc\u0648\u0646\u06a9\u06c1 \u0633\u06cc\u0679 \u0627\u067e \u062a\u06a9\u0644\u06cc\u0641 \u062f\u06c1 \u06c1\u06d2\u06d4 \u0627\u0633 \u0645\u0636\u0645\u0648\u0646 \u06a9\u06cc \u062a\u0645\u0627\u0645 \u0627\u0633\u06a9\u0631\u06cc\u0646\u0648\u06ba \u0645\u06cc\u06ba \u0644\u0648\u0688\u0646\u06af \u06a9\u06cc \u062d\u0627\u0644\u062a\u060c \u0627\u06cc\u06a9 \u062e\u0631\u0627\u0628\u06cc \u06a9\u06cc \u062d\u0627\u0644\u062a\u060c \u0627\u0648\u0631 \u06a9\u0627\u0645\u06cc\u0627\u0628\u06cc \u06a9\u06cc \u062d\u0627\u0644\u062a \u06c1\u06d2\u060c \u0627\u0648\u0631 \u0627\u0628\u062a\u062f\u0627\u0626\u06cc \u0637\u0648\u0631 \u067e\u0631 \u0645\u06cc\u06ba \u0646\u06d2 \u06a9\u0626\u06cc \u0679\u06cc\u0645\u0648\u06ba \u06a9\u0648 \u062f\u06cc\u06a9\u06be\u0627\u060c \u062c\u0646 \u0645\u06cc\u06ba \u0645\u06cc\u0631\u06cc \u0628\u06be\u06cc \u0634\u0627\u0645\u0644 \u06c1\u06d2\u060c \u0645\u06a9\u0645\u0644 \u0637\u0648\u0631 \u067e\u0631 \u06a9\u0627\u0645\u06cc\u0627\u0628\u06cc \u06a9\u06d2 \u0644\u06cc\u06d2 \u0648\u06cc\u062c\u06cc\u0679 \u0679\u06cc\u0633\u0679 \u0644\u06a9\u06be\u062a\u06d2 \u06c1\u06cc\u06ba\u06d4 \u06a9\u06cc\u0648\u0646\u06a9\u06c1 \u0627\u0633\u06d2 \u062a\u0631\u062a\u06cc\u0628 \u062f\u06cc\u0646\u0627 \u0622\u0633\u0627\u0646 \u06c1\u06d2\u06d4 \u062e\u0631\u0627\u0628\u06cc \u06a9\u06cc \u062d\u0627\u0644\u062a\u06cc\u06ba \u0627\u0635\u0644 \u06a9\u06cc\u0691\u06d2 \u067e\u0631 \u0645\u0634\u062a\u0645\u0644 \u06c1\u0648\u0646\u06d2 \u06a9\u0627 \u0633\u0628 \u0633\u06d2 \u0632\u06cc\u0627\u062f\u06c1 \u0627\u0645\u06a9\u0627\u0646 \u06c1\u06d2 \u06a9\u06cc\u0648\u0646\u06a9\u06c1 \u06cc\u06c1 \u0648\u06c1 \u0631\u0627\u0633\u062a\u06d2 \u06c1\u06cc\u06ba \u062c\u0648 \u0688\u0648\u06cc\u0644\u067e\u0631 \u062f\u0633\u062a\u06cc \u062c\u0627\u0646\u0686 \u06a9\u06d2 \u062f\u0648\u0631\u0627\u0646 \u06a9\u0645 \u0633\u06d2 \u06a9\u0645 \u0627\u062e\u062a\u06cc\u0627\u0631 \u06a9\u0631\u062a\u06d2 \u06c1\u06cc\u06ba\u06d4<\/p>\n<p>\u063a\u06cc\u0631 \u0645\u0633\u062a\u062d\u06a9\u0645 \u0679\u06cc\u0633\u0679\u0648\u06ba \u06a9\u0648 \u0627\u06cc\u0633\u06cc \u0686\u06cc\u0632 \u0633\u0645\u062c\u06be\u0646\u0627 \u0628\u06be\u06cc \u0627\u06cc\u06a9 \u063a\u0644\u0637\u06cc \u06c1\u06d2 \u062c\u0633\u06d2 \u062f\u0631\u0633\u062a \u06a9\u0631\u0646\u06d2 \u06a9\u06d2 \u0628\u062c\u0627\u0626\u06d2 \u062f\u0648\u0628\u0627\u0631\u06c1 \u06a9\u0648\u0634\u0634 \u06a9\u0631\u0646\u06d2 \u06a9\u06cc \u0636\u0631\u0648\u0631\u062a \u06c1\u06d2\u06d4 \u0627\u06cc\u06a9 \u0679\u06cc\u0633\u0679 \u062c\u0648 20 \u0628\u0627\u0631 \u0645\u06cc\u06ba \u0627\u06cc\u06a9 \u0628\u0627\u0631 \u0646\u0627\u06a9\u0627\u0645 \u06c1\u0648 \u062c\u0627\u062a\u0627 \u06c1\u06d2 \u0627\u0648\u0631 \u062f\u0648\u0628\u0627\u0631\u06c1 \u0686\u0644\u0627\u0646\u06d2 \u067e\u0631 \u067e\u0627\u0633 \u06c1\u0648\u062a\u0627 \u06c1\u06d2 \u0648\u06c1 &quot;\u06a9\u0628\u06be\u06cc \u06a9\u0628\u06be\u06cc \u063a\u06cc\u0631 \u0645\u0633\u062a\u062d\u06a9\u0645&#8221; \u0679\u06cc\u0633\u0679 \u0646\u06c1\u06cc\u06ba \u06c1\u0648\u062a\u0627 \u06c1\u06d2\u06d4 \u06cc\u06c1 \u0622\u067e \u06a9\u0648 \u0622\u067e \u06a9\u06d2 \u06a9\u0648\u0688 \u0645\u06cc\u06ba \u0631\u06cc\u0633 \u06a9\u06d2 \u062d\u0627\u0644\u0627\u062a \u06cc\u0627 \u0648\u0642\u062a \u06a9\u06d2 \u0628\u0627\u0631\u06d2 \u0645\u06cc\u06ba \u0645\u0641\u0631\u0648\u0636\u0648\u06ba \u06a9\u06cc \u062c\u0627\u0646\u0686 \u06a9\u06d2 \u0628\u0627\u0631\u06d2 \u0645\u06cc\u06ba \u06a9\u0686\u06be \u062d\u0642\u06cc\u0642\u06cc \u0628\u062a\u0627\u062a\u0627 \u06c1\u06d2\u06d4 \u0627\u06af\u0631 \u0622\u067e \u0627\u0633\u06d2 \u0627\u067e\u0646\u06d2 CI \u0645\u06cc\u06ba \u062e\u0648\u062f\u06a9\u0627\u0631 \u062f\u0648\u0628\u0627\u0631\u06c1 \u06a9\u0648\u0634\u0634\u0648\u06ba \u06a9\u06d2 \u0633\u0627\u062a\u06be \u062e\u0627\u0645\u0648\u0634 \u06a9\u0631 \u062f\u06cc\u062a\u06d2 \u06c1\u06cc\u06ba\u060c \u062a\u0648 \u0622\u067e \u06a9\u06cc \u067e\u0648\u0631\u06cc \u0679\u06cc\u0645 \u0622\u067e \u06a9\u06d2 \u0631\u06cc\u0688 \u0628\u0644\u0688\u0632 \u067e\u0631 \u0628\u06be\u0631\u0648\u0633\u06c1 \u06a9\u0631\u0646\u0627 \u0686\u06be\u0648\u0691 \u062f\u06d2 \u06af\u06cc\u06d4 \u06cc\u06c1 \u063a\u06cc\u0631 \u0645\u0633\u062a\u062d\u06a9\u0645 \u0679\u06cc\u0633\u0679 \u0633\u06d2 \u06a9\u06c1\u06cc\u06ba \u0632\u06cc\u0627\u062f\u06c1 \u0645\u06c1\u0646\u06af\u0627 \u0645\u0633\u0626\u0644\u06c1 \u06c1\u06d2\u06d4<\/p>\n<p>\u0627\u0648\u0631 \u0622\u062e\u0631 \u06a9\u0627\u0631\u060c \u0627\u06cc\u0633\u06d2 \u0679\u06cc\u0633\u0679 \u0644\u06a9\u06be\u0646\u0627 \u0627\u06cc\u06a9 \u063a\u0644\u0637\u06cc \u06c1\u06d2 \u062c\u0648 \u0631\u0648\u06cc\u06d2 \u06a9\u06d2 \u0628\u062c\u0627\u0626\u06d2 \u0639\u0645\u0644 \u062f\u0631\u0622\u0645\u062f \u06a9\u06cc \u062a\u0641\u0635\u06cc\u0644\u0627\u062a \u06a9\u0648 \u0686\u06cc\u06a9 \u06a9\u0631\u062a\u06d2 \u06c1\u06cc\u06ba\u06d4 \u0686\u06cc\u06a9 \u06a9\u0631\u0646\u06d2 \u06a9\u06d2 \u0644\u0626\u06d2 \u0679\u06cc\u0633\u0679 <code>notifier._tasks.length<\/code> (\u0646\u062c\u06cc \u0641\u06cc\u0644\u0688) \u0627\u0633 \u06a9\u06d2 \u0628\u062c\u0627\u0626\u06d2 <code>notifier.tasks.length<\/code> \u06cc\u0627\u060c \u067e\u06cc\u0634 \u06a9\u0631\u062f\u06c1 UI \u0679\u06cc\u0633\u0679\u0648\u06ba \u06a9\u0648 \u0627\u0646\u062f\u0631\u0648\u0646\u06cc \u0688\u06be\u0627\u0646\u0686\u06d2 \u0633\u06d2 \u062c\u0648\u0691\u062a\u0627 \u06c1\u06d2 \u062c\u0646 \u06a9\u0627 \u06a9\u0648\u0626\u06cc \u06a9\u0627\u0631\u0648\u0628\u0627\u0631 \u0628\u0631\u0627\u06c1 \u0631\u0627\u0633\u062a \u0679\u06cc\u0633\u0679 \u0646\u06c1\u06cc\u06ba \u06c1\u0648\u062a\u0627 \u06c1\u06d2\u06d4 \u062c\u0633 \u0644\u0645\u062d\u06d2 \u0622\u067e \u0627\u0635\u0644 \u0631\u0648\u06cc\u06d2 \u06a9\u0648 \u062a\u0628\u062f\u06cc\u0644 \u06a9\u06cc\u06d2 \u0628\u063a\u06cc\u0631 \u062f\u0627\u062e\u0644\u06cc \u0646\u0645\u0627\u0626\u0646\u062f\u06af\u06cc \u06a9\u0648 \u0631\u06cc \u0641\u06cc\u06a9\u0679\u0631 \u06a9\u0631\u06cc\u06ba \u06af\u06d2\u060c \u0622\u067e \u06a9\u06d2 \u0679\u06cc\u0633\u0679 \u0627\u0646 \u0648\u062c\u0648\u06c1\u0627\u062a \u06a9\u06cc \u0628\u0646\u0627 \u067e\u0631 \u0679\u0648\u0679 \u062c\u0627\u0626\u06cc\u06ba \u06af\u06d2 \u062c\u0646 \u06a9\u0627 \u0627\u0635\u0644 \u0628\u06af \u0633\u06d2 \u06a9\u0648\u0626\u06cc \u062a\u0639\u0644\u0642 \u0646\u06c1\u06cc\u06ba \u06c1\u06d2\u06d4<\/p>\n<h2 id=\"heading-running-everything-together\">\u0633\u0628 \u06a9\u0686\u06be \u0627\u06cc\u06a9 \u0633\u0627\u062a\u06be \u0686\u0644\u0627\u0626\u06cc\u06ba<\/h2>\n<p>\u06a9\u0648\u0626\u06cc \u0631\u0627\u0633\u062a\u06c1 \u0646\u06c1\u06cc\u06ba <code>Makefile<\/code> \u0645\u062a\u0628\u0627\u062f\u0644 \u0637\u0648\u0631 \u067e\u0631\u060c \u0627\u06cc\u06a9 CI \u0627\u0633\u06a9\u0631\u067e\u0679 \u062c\u0648 \u0686\u0627\u0631\u0648\u06ba \u062a\u0631\u062a\u06cc\u0628 \u0633\u06d2 \u0686\u0644\u062a\u0627 \u06c1\u06d2 (\u0633\u0628 \u0633\u06d2 \u0633\u0633\u062a\u0627 \u067e\u06c1\u0644\u06d2) \u0634\u0631\u0648\u0639 \u06c1\u0648\u0646\u06d2 \u0633\u06d2 \u067e\u06c1\u0644\u06d2 \u06c1\u06cc \u0633\u0628 \u0633\u06d2 \u0645\u06c1\u0646\u06af\u06d2 \u0645\u0633\u0627\u0626\u0644 \u06a9\u0648 \u067e\u06a9\u0691 \u0644\u06d2 \u06af\u0627\u06d4<\/p>\n<pre><code class=\"language-bash\"># Fails fast on logic bugs before spending time on anything else.\nflutter test test\/task_logic_test.dart\n\n# Widget-level behavior across all three UI states.\nflutter test test\/task_screen_test.dart\n\n# Visual regressions on the screens that matter.\nflutter test test\/task_screen_golden_test.dart\n\n# The real thing, on a real device or emulator \u2014 last, because it's slowest.\nflutter test integration_test\/complete_task_test.dart\n<\/code><\/pre>\n<p>CI \u06c1\u0631 \u067e\u0644 \u06a9\u06cc \u062f\u0631\u062e\u0648\u0627\u0633\u062a \u06a9\u06d2 \u0644\u06cc\u06d2 \u067e\u06c1\u0644\u06d2 \u062a\u06cc\u0646 \u0686\u0644\u0627\u062a\u0627 \u06c1\u06d2\u06d4 \u0648\u06c1 \u0627\u062a\u0646\u06d2 \u062a\u06cc\u0632 \u06c1\u06cc\u06ba \u06a9\u06c1 \u06a9\u0648\u0626\u06cc \u0639\u0630\u0631 \u0646\u06c1\u06cc\u06ba \u06c1\u06d2\u06d4 \u0627\u0646\u0679\u06cc\u06af\u0631\u06cc\u0679\u0688 \u0633\u0648\u06cc\u0679\u0633 \u06a9\u0648 \u0627\u067e\u0646\u06d2 \u0645\u06cc\u0646 \u06cc\u0627 \u0631\u0627\u062a \u06a9\u06d2 \u0634\u06cc\u0688\u0648\u0644 \u0645\u06cc\u06ba \u0636\u0645 \u06a9\u0631\u06a9\u06d2 \u0686\u0644\u0627\u0626\u06cc\u06ba\u06d4 \u0686\u0648\u0646\u06a9\u06c1 \u0627\u0633 \u06a9\u06d2 \u0644\u06cc\u06d2 \u0627\u06cc\u06a9 \u062d\u0642\u06cc\u0642\u06cc \u0688\u06cc\u0648\u0627\u0626\u0633 \u06cc\u0627 \u0627\u06cc\u0645\u0648\u0644\u06cc\u0679\u0631 \u06a9\u06cc \u0636\u0631\u0648\u0631\u062a \u06c1\u0648\u062a\u06cc \u06c1\u06d2 \u0627\u0648\u0631 \u062a\u0645\u0627\u0645 PRs \u06a9\u0648 \u0628\u0644\u0627\u06a9 \u06a9\u0631\u0646\u06d2 \u06a9\u06d2 \u0644\u06cc\u06d2 \u06a9\u0627\u0641\u06cc \u0648\u0642\u062a \u0644\u06af\u062a\u0627 \u06c1\u06d2\u060c \u0627\u0633 \u0644\u06cc\u06d2 \u06cc\u06c1 \u0679\u06cc\u0645 \u06a9\u0648 \u0627\u0646 \u06a9\u06cc\u0679\u06cc\u06af\u0631\u06cc\u0632 \u06a9\u06d2 \u06a9\u06cc\u0691\u06d2 \u06a9\u06d2 \u0644\u06cc\u06d2 \u0633\u0633\u062a \u06a9\u0631 \u062f\u06cc\u062a\u0627 \u06c1\u06d2 \u062c\u0646\u06c1\u06cc\u06ba \u0627\u06cc\u06a9 \u0627\u0686\u06be\u0627 \u0648\u06cc\u062c\u06cc\u0679 \u0679\u06cc\u0633\u0679\u0646\u06af \u0633\u0648\u0679 \u067e\u06c1\u0644\u06d2 \u06c1\u06cc \u0632\u06cc\u0627\u062f\u06c1 \u062a\u0631 \u0648\u0642\u062a \u067e\u06a9\u0691\u062a\u0627 \u06c1\u06d2\u06d4<\/p>\n<h2 id=\"heading-end-to-end-all-four-layers-on-one-ci-pipeline\">\u0622\u062e\u0631 \u0633\u06d2 \u0622\u062e\u0631 \u062a\u06a9: \u0627\u06cc\u06a9 CI \u067e\u0627\u0626\u067e \u0644\u0627\u0626\u0646 \u0645\u06cc\u06ba \u0686\u0627\u0631\u0648\u06ba \u067e\u0631\u062a\u06cc\u06ba\u06d4<\/h2>\n<p>\u06cc\u06c1\u0627\u06ba \u06cc\u06c1 \u06c1\u06d2 \u06a9\u06c1 \u0627\u0633\u06d2 \u062d\u0642\u06cc\u0642\u06cc \u067e\u0631\u0648\u062c\u06cc\u06a9\u0679 \u0645\u06cc\u06ba GitHub \u0627\u06cc\u06a9\u0634\u0646\u0632 \u0633\u06d2 \u06a9\u06cc\u0633\u06d2 \u062c\u0648\u0691\u0646\u0627 \u06c1\u06d2: \u067e\u06c1\u0644\u06d2 \u0627\u06cc\u06a9 \u0641\u0648\u0631\u06cc \u062c\u0627\u0646\u0686 \u067e\u0691\u062a\u0627\u0644 \u06a9\u06cc \u062c\u0627\u062a\u06cc \u06c1\u06d2\u060c \u0644\u06c1\u0630\u0627 \u0627\u06af\u0631 \u06a9\u0648\u0626\u06cc \u0645\u0631\u062d\u0644\u06c1 \u0646\u0627\u06a9\u0627\u0645 \u06c1\u0648\u062c\u0627\u062a\u0627 \u06c1\u06d2\u060c \u062a\u0648 \u0627\u06af\u0644\u06d2 \u0645\u0631\u062d\u0644\u06d2 \u067e\u0631 \u0648\u0642\u062a \u0636\u0627\u0626\u0639 \u06c1\u0648\u0646\u06d2 \u0633\u06d2 \u067e\u06c1\u0644\u06d2 \u067e\u0627\u0626\u067e \u0644\u0627\u0626\u0646 \u06a9\u0648 \u0631\u0648\u06a9 \u062f\u06cc\u0627 \u062c\u0627\u062a\u0627 \u06c1\u06d2\u06d4<\/p>\n<pre><code class=\"language-yaml\"># .github\/workflows\/test.yml\nname: Test\n\non: [pull_request, push]\n\njobs:\n  unit-and-widget:\n    runs-on: ubuntu-latest\n    steps:\n      - uses: actions\/checkout@v4\n      - uses: subosito\/flutter-action@v2\n      - run: flutter pub get\n      # Unit and widget tests together \u2014 both fast, both run on\n      # every PR without a second thought about cost.\n      - run: flutter test test\/task_logic_test.dart test\/task_screen_test.dart\n\n  golden:\n    runs-on: ubuntu-latest\n    needs: unit-and-widget\n    steps:\n      - uses: actions\/checkout@v4\n      - uses: subosito\/flutter-action@v2\n      - run: flutter pub get\n      - run: flutter test test\/task_screen_golden_test.dart\n      # Upload diffs so a reviewer can see exactly what changed\n      # without pulling the branch locally \u2014 this is what keeps\n      # golden failures from becoming a rubber-stamped --update-goldens.\n      - uses: actions\/upload-artifact@v4\n        if: failure()\n        with:\n          name: golden-diffs\n          path: test\/failures\/\n\n  integration:\n    runs-on: macos-latest # needed for iOS simulator; use ubuntu + Android emulator otherwise\n    needs: golden\n    if: github.ref == 'refs\/heads\/main' # only on merges to main, not every PR\n    steps:\n      - uses: actions\/checkout@v4\n      - uses: subosito\/flutter-action@v2\n      - run: flutter pub get\n      - run: flutter test integration_test\/complete_task_test.dart -d \"iPhone 15\"\n<\/code><\/pre>\n<p>\u06a9\u06c1 <code>needs:<\/code> \u0632\u0646\u062c\u06cc\u0631 \u0627\u0648\u0631 <code>if:<\/code> \u0627\u0646\u0636\u0645\u0627\u0645 \u06a9\u06d2 \u06a9\u0627\u0645 \u06a9\u06d2 \u062d\u0627\u0644\u0627\u062a \u0648\u06c1 \u06c1\u06cc\u06ba \u062c\u06c1\u0627\u06ba \u062d\u0642\u06cc\u0642\u06cc \u06a9\u0627\u0645 \u06a9\u06cc\u0627 \u062c\u0627\u062a\u0627 \u06c1\u06d2\u06d4 \u06cc\u06c1 \u0633\u0628 \u0633\u06d2 \u0633\u0633\u062a \u0627\u0648\u0631 \u0645\u06c1\u0646\u06af\u06d2 \u0686\u06cc\u06a9\u0648\u06ba \u06a9\u0648 \u06c1\u0631 \u0627\u06cc\u06a9 \u067e\u0634 \u067e\u0631 \u0686\u0644\u0646\u06d2 \u0633\u06d2 \u0631\u0648\u06a9\u062a\u0627 \u06c1\u06d2\u060c \u062c\u0628\u06a9\u06c1 \u0627\u0633 \u0628\u0627\u062a \u06a9\u0648 \u0628\u06be\u06cc \u06cc\u0642\u06cc\u0646\u06cc \u0628\u0646\u0627\u062a\u0627 \u06c1\u06d2 \u06a9\u06c1 \u0648\u06c1 \u06a9\u0633\u06cc \u0628\u06be\u06cc \u0686\u06cc\u0632 \u06a9\u06d2 \u067e\u06c1\u0646\u0686\u0646\u06d2 \u0633\u06d2 \u067e\u06c1\u0644\u06d2 \u06c1\u06cc \u0686\u0644\u062a\u06d2 \u06c1\u06cc\u06ba\u06d4 <code>main<\/code>.<\/p>\n<h2 id=\"heading-final-thoughts\">\u062d\u062a\u0645\u06cc \u062e\u06cc\u0627\u0644\u0627\u062a<\/h2>\n<p>\u0645\u06cc\u06ba &quot;\u0679\u06cc\u0633\u0679&#8221; \u06a9\u06d2 \u0628\u0627\u0631\u06d2 \u0645\u06cc\u06ba \u0627\u06cc\u06a9 \u0648\u0627\u062d\u062f \u0622\u0626\u0679\u0645 \u06a9\u06d2 \u0637\u0648\u0631 \u067e\u0631 \u0633\u0648\u0686\u062a\u0627 \u062a\u06be\u0627\u060c \u062c\u0648 \u06a9\u0686\u06be \u06a9\u06cc\u0627 \u06af\u06cc\u0627 \u062a\u06be\u0627 \u06cc\u0627 \u0646\u06c1\u06cc\u06ba \u06a9\u06cc\u0627 \u06af\u06cc\u0627 \u062a\u06be\u0627\u060c \u0688\u06cc\u0634 \u0628\u0648\u0631\u0688 \u06a9\u0627 \u0627\u06cc\u06a9 \u0641\u06cc\u0635\u062f\u06d4 \u06cc\u06c1 \u0633\u0686 \u0646\u06c1\u06cc\u06ba \u06c1\u06d2\u06d4 \u06cc\u0648\u0646\u0679 \u0679\u06cc\u0633\u0679 \u0622\u067e \u06a9\u06cc \u0645\u0646\u0637\u0642 \u06a9\u06cc \u062d\u0641\u0627\u0638\u062a \u06a9\u0631\u062a\u06d2 \u06c1\u06cc\u06ba\u06d4 \u0648\u06cc\u062c\u06cc\u0679 \u0679\u06cc\u0633\u0679 \u0631\u06cc\u0627\u0633\u062a \u06a9\u06cc \u062d\u0641\u0627\u0638\u062a \u06a9\u0631\u062a\u06d2 \u06c1\u06cc\u06ba\u06d4 \u06af\u0648\u0644\u0688\u0646 \u0679\u06cc\u0633\u0679 \u0622\u067e \u06a9\u06d2 \u067e\u06a9\u0633\u0644\u0632 \u06a9\u06cc \u062d\u0641\u0627\u0638\u062a \u06a9\u0631\u062a\u0627 \u06c1\u06d2\u06d4 \u0627\u0646\u0679\u06cc\u06af\u0631\u06cc\u0634\u0646 \u0679\u06cc\u0633\u0679\u0646\u06af \u0627\u0633 \u0648\u0639\u062f\u06d2 \u06a9\u06cc \u062d\u0641\u0627\u0638\u062a \u06a9\u0631\u062a\u06cc \u06c1\u06d2 \u06a9\u06c1 \u0627\u0635\u0644 \u0645\u06cc\u06ba \u0627\u06cc\u06a9 \u062d\u0642\u06cc\u0642\u06cc \u0688\u06cc\u0648\u0627\u0626\u0633 \u067e\u0631 \u0633\u0628 \u06a9\u0686\u06be \u0645\u0644 \u06a9\u0631 \u06a9\u0627\u0645 \u06a9\u0631\u06d2 \u06af\u0627\u06d4<\/p>\n<p>\u0627\u06cc\u06a9 \u0628\u0627\u0631 \u062c\u0628 \u0622\u067e \u0627\u0635\u0644 \u0641\u0639\u0627\u0644\u06cc\u062a \u0642\u0627\u0626\u0645 \u06a9\u0631 \u0644\u06cc\u062a\u06d2 \u06c1\u06cc\u06ba \u062a\u0648 \u0627\u0646 \u0645\u06cc\u06ba \u0633\u06d2 \u06a9\u0648\u0626\u06cc \u0628\u06be\u06cc \u0644\u06a9\u06be\u0646\u0627 \u0645\u0634\u06a9\u0644 \u0646\u06c1\u06cc\u06ba \u06c1\u0648\u062a\u0627\u06d4 \u0627\u0633\u06cc \u0644\u06cc\u06d2 \u0645\u06cc\u06ba \u0646\u06d2 \u06cc\u06c1 \u0645\u0636\u0645\u0648\u0646 \u0686\u0627\u0631 \u0645\u0646\u0642\u0637\u0639 \u0679\u06a9\u0691\u0648\u06ba \u06a9\u06cc \u0628\u062c\u0627\u0626\u06d2 \u0627\u06cc\u06a9 \u062e\u0635\u0648\u0635\u06cc\u062a \u06a9\u06d2 \u06af\u0631\u062f \u0644\u06a9\u06be\u0627 \u06c1\u06d2\u06d4 \u06a9\u0627\u0645 \u06a9\u06cc \u062a\u06a9\u0645\u06cc\u0644 \u06a9\u0627 \u0628\u06af \u062c\u0633 \u0646\u06d2 \u0627\u0633 \u0645\u0636\u0645\u0648\u0646 \u06a9\u0648 \u0634\u0631\u0648\u0639 \u06a9\u06cc\u0627 (\u0627\u06cc\u06a9 \u06a9\u0627\u0645 \u062c\u0633 \u06a9\u0648 \u063a\u0644\u0637 \u0641\u06c1\u0631\u0633\u062a \u0645\u06cc\u06ba \u0645\u06a9\u0645\u0644 \u06a9\u06d2 \u0637\u0648\u0631 \u067e\u0631 \u0646\u0634\u0627\u0646 \u0632\u062f \u06a9\u06cc\u0627 \u06af\u06cc\u0627 \u06c1\u06d2) \u0634\u0627\u06cc\u062f \u0627\u06cc\u06a9 \u06cc\u0648\u0646\u0679 \u0679\u06cc\u0633\u0679 \u0645\u06cc\u06ba \u062f\u0631\u06cc\u0627\u0641\u062a \u06a9\u06cc\u0627 \u06af\u06cc\u0627 \u062a\u06be\u0627\u06d4 <code>markDone<\/code>\u0648\u06cc\u062c\u06cc\u0679 \u067e\u0631\u062a \u06a9\u0648 \u0686\u06be\u0648\u0646\u06d2 \u0633\u06d2 \u067e\u06c1\u0644\u06d2 \u0644\u06a9\u06be\u0627 \u06af\u06cc\u0627\u06d4<\/p>\n<p>\u0645\u06cc\u06ba \u0627\u0633 \u0679\u06cc\u0633\u0679 \u06a9\u0648 \u0644\u06a9\u06be\u0646\u06d2 \u0648\u0627\u0644\u0627 \u067e\u06c1\u0644\u0627 \u0646\u06c1\u06cc\u06ba \u062a\u06be\u0627\u06d4 \u0627\u0628 \u0645\u06cc\u06ba \u0627\u0633 \u0627\u0648\u0631 \u0627\u0633 \u06a9\u06d2 \u0628\u06c1\u0646 \u0628\u06be\u0627\u0626\u06cc\u0648\u06ba \u06a9\u06cc \u062a\u0645\u0627\u0645 \u0627\u06c1\u0645 \u062e\u0635\u0648\u0635\u06cc\u0627\u062a \u06a9\u06d2 \u0628\u0627\u0631\u06d2 \u0645\u06cc\u06ba \u0644\u06a9\u06be \u0631\u06c1\u0627 \u06c1\u0648\u06ba\u06d4 \u06cc\u06c1 \u0627\u0635\u0644 \u0645\u06cc\u06ba \u067e\u0648\u0631\u0627 \u0633\u0628\u0642 \u06c1\u06d2\u06d4 \u0627\u06cc\u0633\u0627 \u0646\u06c1\u06cc\u06ba \u06c1\u06d2 \u06a9\u06c1 \u0679\u06cc\u0633\u0679 \u067e\u06cc\u0686\u06cc\u062f\u06c1 \u06c1\u06cc\u06ba\u060c \u06cc\u06c1 \u06c1\u06d2 \u06a9\u06c1 \u0686\u0627\u0631 \u0627\u0642\u0633\u0627\u0645 \u0645\u06cc\u06ba \u0633\u06d2 \u06c1\u0631 \u0627\u06cc\u06a9 \u0627\u06cc\u0633\u06d2 \u0633\u0648\u0627\u0644\u0627\u062a \u06a9\u06d2 \u062c\u0648\u0627\u0628\u0627\u062a \u062f\u06cc\u062a\u0627 \u06c1\u06d2 \u062c\u0648 \u062f\u06cc\u06af\u0631 \u062a\u06cc\u0646 \u0627\u0642\u0633\u0627\u0645 \u0646\u06c1\u06cc\u06ba \u062f\u06d2 \u0633\u06a9\u062a\u06d2\u06d4<\/p>\n<\/p><\/div>\n","protected":false},"excerpt":{"rendered":"<p>\u067e\u06c1\u0644\u06cc \u0628\u0627\u0631\u060c \u0645\u062c\u06be \u0633\u06d2 \u0633\u0648\u0627\u0644 \u067e\u0648\u0686\u06be\u0627 \u06af\u06cc\u0627\u060c &quot;\u0679\u06cc\u0633\u0679\u0646\u06af \u06a9\u0627 \u062f\u0627\u0626\u0631\u06c1 \u06a9\u06cc\u0627 \u06c1\u06d2\u061f&#8221; \u0645\u062c\u06be\u06d2 \u062a\u06a9\u0646\u06cc\u06a9\u06cc \u0627\u0646\u0679\u0631\u0648\u06cc\u0648 \u0645\u06cc\u06ba \u0627\u0686\u06be\u06d2 \u062c\u0648\u0627\u0628 \u0646\u06c1\u06cc\u06ba \u0645\u0644\u06d2\u06d4 \u062a\u0628 \u062a\u06a9\u060c \u0645\u06cc\u06ba \u0646\u06d2 \u0686\u0646\u062f \u062d\u0642\u06cc\u0642\u06cc \u0641\u0644\u0679\u0631 \u0627\u06cc\u067e\u0633 \u062c\u0627\u0631\u06cc \u06a9\u0631 \u062f\u06cc \u062a\u06be\u06cc\u06ba\u06d4 \u0648\u06c1 \u06a9\u0627\u0645 \u06a9\u0631 \u0631\u06c1\u06d2 \u062a\u06be\u06d2 \u0627\u0648\u0631 \u0635\u0627\u0631\u0641 \u0627\u0646\u06c1\u06cc\u06ba \u0627\u0633\u062a\u0639\u0645\u0627\u0644 \u06a9\u0631 \u0631\u06c1\u06d2 \u062a\u06be\u06d2\u06d4 \u0644\u06cc\u06a9\u0646 \u0645\u06cc\u0631\u06d2 \u0679\u06cc\u0633\u0679\u060c \u0627\u06af\u0631 \u0622\u067e \u0627\u0646\u06c1\u06cc\u06ba \u06a9\u06c1\u06c1 \u0633\u06a9\u062a\u06d2 \u06c1\u06cc\u06ba\u060c \u062a\u0648 \u0642\u06cc\u0645\u062a\u0648\u06ba [&hellip;]<\/p>\n","protected":false},"author":7,"featured_media":0,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"site-sidebar-layout":"default","site-content-layout":"","ast-site-content-layout":"default","site-content-style":"default","site-sidebar-style":"default","ast-global-header-display":"","ast-banner-title-visibility":"","ast-main-header-display":"","ast-hfb-above-header-display":"","ast-hfb-below-header-display":"","ast-hfb-mobile-header-display":"","site-post-title":"","ast-breadcrumbs-content":"","ast-featured-img":"","footer-sml-layout":"","ast-disable-related-posts":"","theme-transparent-header-meta":"","adv-header-id-meta":"","stick-header-meta":"","header-above-stick-meta":"","header-main-stick-meta":"","header-below-stick-meta":"","astra-migrate-meta-layouts":"default","ast-page-background-enabled":"default","ast-page-background-meta":{"desktop":{"background-color":"var(--ast-global-color-5)","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""},"tablet":{"background-color":"","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""},"mobile":{"background-color":"","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""}},"ast-content-background-meta":{"desktop":{"background-color":"var(--ast-global-color-4)","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""},"tablet":{"background-color":"var(--ast-global-color-4)","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""},"mobile":{"background-color":"var(--ast-global-color-4)","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""}},"footnotes":""},"categories":[1],"tags":[],"class_list":["post-28445","post","type-post","status-publish","format-standard","hentry","category-blog"],"_links":{"self":[{"href":"https:\/\/umang.pk\/ur\/wp-json\/wp\/v2\/posts\/28445","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/umang.pk\/ur\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/umang.pk\/ur\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/umang.pk\/ur\/wp-json\/wp\/v2\/users\/7"}],"replies":[{"embeddable":true,"href":"https:\/\/umang.pk\/ur\/wp-json\/wp\/v2\/comments?post=28445"}],"version-history":[{"count":0,"href":"https:\/\/umang.pk\/ur\/wp-json\/wp\/v2\/posts\/28445\/revisions"}],"wp:attachment":[{"href":"https:\/\/umang.pk\/ur\/wp-json\/wp\/v2\/media?parent=28445"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/umang.pk\/ur\/wp-json\/wp\/v2\/categories?post=28445"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/umang.pk\/ur\/wp-json\/wp\/v2\/tags?post=28445"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}