рдирдорд╕реНрдХрд╛рд░, рд╣реЗрдмреНрд░!
рдЗрд╕ рд▓реЗрдЦ рдореЗрдВ рд╣рдо рдХрдИ рдХреНрдпреВрдЖрдИрдбрдмреНрд▓реНрдпреВрдЖрдИ рдкрд░рд┐рдпреЛрдЬрдирд╛рдУрдВ рдореЗрдВ рд╕реЗ рдПрдХ рдкрд░ рд╕реНрд╡рдЪрд╛рд▓рд┐рдд рдкрд░реАрдХреНрд╖рдг рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдмрд╛рдд рдХрд░реЗрдВрдЧреЗ, рдЬрд┐рд╕рдХрд╛ рдирд╛рдо "рдХреЗ" рдХреЛрдб рд╣реИред

рдЬрдм рд╣рдордиреЗ рдЗрд╕ рдкрд░рд┐рдпреЛрдЬрдирд╛ рдХрд╛ рдкрд░реАрдХреНрд╖рдг рдЖрдпреЛрдЬрд┐рдд рдХрд┐рдпрд╛, рддреЛ рд╣рдордиреЗ рд╡реНрдпрд╛рд╡рд╣рд╛рд░рд┐рдХ рдФрд░ рдкреНрд░рдЪрд╛рд░
рдХреЛрдЯрд▓рд┐рди рдХреЗ рд╕рд╛рде-рд╕рд╛рде
рд╕реНрдкреЗрдХ рдХреЛ рдЪреБрдирдиреЗ рдХрд╛ рдлреИрд╕рд▓рд╛ рдХрд┐рдпрд╛, рдЬреЛ рдХрд╣рддрд╛ рд╣реИ рдХрд┐ "рдЖрдк рдЙрдиреНрд╣реЗрдВ рдкрд░реАрдХреНрд╖рдг рдХрд╣рддреЗ рд╣реИрдВ, рд╣рдо рдЙрдиреНрд╣реЗрдВ рд╡рд┐рдирд┐рд░реНрджреЗрд╢рди рдХрд╣рддреЗ рд╣реИрдВ" (рдЖрдк рдЙрдиреНрд╣реЗрдВ рдкрд░реАрдХреНрд╖рдг рдХрд╣рддреЗ рд╣реИрдВ, рд╣рдо рдЙрдиреНрд╣реЗрдВ рд╡рд┐рдирд┐рд░реНрджреЗрд╢реЛрдВ рдХрд╣рддреЗ рд╣реИрдВ)ред рдпрджрд┐ рдЖрдк рдЗрд╕реА рддрд░рд╣ рдХреЗ рдХрд╛рд░реНрдпреЛрдВ рдХрд╛ рд╕рд╛рдордирд╛ рдХрд░ рд░рд╣реЗ рд╣реИрдВ рддреЛ рд╢рд╛рдпрдж рдпрд╣ рджреГрд╖реНрдЯрд┐рдХреЛрдг рдЖрдкрдХреЗ рд▓рд┐рдП рдЙрдкрдпреБрдХреНрдд рд╣реИред
рдХреЛрдЯрд▓рд┐рди рдФрд░ рдХреБрдЫ рдФрд░ рдХреНрдпреЛрдВ рдирд╣реАрдВ? рдХреЛрдЯрд▓рд┐рди рдХреЛ рд╡рд┐рдХрд╛рд╕ рджреНрд╡рд╛рд░рд╛ рдЪреБрдирд╛ рдЧрдпрд╛ рдерд╛, рдкреНрд░рдпреЛрдЧ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП, рдХреНрдпреЛрдВрдХрд┐ рдпрд╣ рд╡рд┐рд╢реЗрд╖ рдЙрддреНрдкрд╛рдж рдорд╣рддреНрд╡рдкреВрд░реНрдг рдирд╣реАрдВ рдерд╛, рдФрд░ рдпрд╣ рд╕рдВрднрд╡ рдерд╛ рдХрд┐ рдмрд┐рдирд╛ рдХрд┐рд╕реА рдбрд░ рдХреЗ рдЗрд╕реЗ рд▓рд╛рдЗрд╡ рдЕрднреНрдпрд╛рд╕ рдХрд░реЗрдВ рдЬрд┐рд╕рд╕реЗ рдХрд┐ рд╕рдорд╕реНрдпрд╛рдПрдВ рд╣реЛрдВред
рдЖрдзрд┐рдХрд╛рд░рд┐рдХ
рджрд╕реНрддрд╛рд╡реЗрдЬ рд╣рдореЗрдВ рдмрддрд╛рддрд╛ рд╣реИ рдХрд┐ "рд╕реНрдкреЗрдХ рдХреЛрдЯрд▓рд┐рди рдореЗрдВ рд▓рд┐рдЦрд╛ рдЧрдпрд╛ рд╣реИ, рдФрд░ рдЖрдкрдХреЗ рджреНрд╡рд╛рд░рд╛ рд▓рд┐рдЦреЗ рдЧрдП рд╡рд┐рдирд┐рд░реНрджреЗрд╢реЛрдВ рдХреЛ рдХреЛрдЯрд▓рд┐рди рдореЗрдВ рд▓рд┐рдЦрд╛ рдЬрд╛рдПрдЧрд╛" - рдпрд╣ рдмрд╣реБрдд рд╕реНрдкрд╖реНрдЯ рд░реВрдк рд╕реЗ рдкреНрд░рд╢реНрди рдХрд╛ рдЙрддреНрддрд░ рджреЗрддрд╛ рд╣реИ: "рдЗрд╕рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рдХреНрдпреЛрдВ рд╣реИ?"
рдЗрд╕рд▓рд┐рдП ...
рдпрд╣ рдХреНрдпрд╛ рд╣реИ рдФрд░ рдЗрд╕рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рдХреНрдпреЛрдВ рд╣реИ?
рдкрд░рд┐рдпреЛрдЬрдирд╛ рдЕрдкрдиреЗ рд╕рд╛рдереА рдХреЛ рд╕реЙрдлреНрдЯрд╡реЗрдпрд░ рдкреНрд░рджрд╛рди рдХрд░рддреА рд╣реИ, рдЬреЛ Android рдХреЗ рд▓рд┐рдП рдПрдХ рдПрдкреНрд▓реАрдХреЗрд╢рди рд╣реИред рд╢реЗрд░ рдХрд╛ рдкрд░реАрдХреНрд╖рдг рдХрд╛ рд╣рд┐рд╕реНрд╕рд╛ рдмреИрдХ-рдПрдВрдб рдкрд░ рдкрдбрд╝рддрд╛ рд╣реИ, рдЗрд╕рд▓рд┐рдП рд╣рдо REST API рдХреЗ рдкрд░реАрдХреНрд╖рдг рдкрд░ рдзреНрдпрд╛рди рдХреЗрдВрджреНрд░рд┐рдд рдХрд░реЗрдВрдЧреЗред
рдПрдХ рдЧреБрдЪреНрдЫрд╛ рдХреЗ рд▓рд┐рдП рдЬреЛ рдЖрдкрдХреЛ рдкрд░реАрдХреНрд╖рдг рд▓рд┐рдЦрдиреЗ рдФрд░ рдкрд░рд┐рдгрд╛рдо рдкреНрд░рд╛рдкреНрдд рдХрд░рдиреЗ рдХреА рдЕрдиреБрдорддрд┐ рджреЗрддрд╛ рд╣реИ, рд╕рдм рдХреБрдЫ рд╕реНрдкрд╖реНрдЯ рд╣реИ: рдЖрдкрдХреЛ рдПрдХ рдкреНрд░реЛрдЧреНрд░рд╛рдорд┐рдВрдЧ рднрд╛рд╖рд╛, рдкрд░реАрдХреНрд╖рдг рд░реВрдкрд░реЗрдЦрд╛, HTTP рдХреНрд▓рд╛рдЗрдВрдЯ рдФрд░ рд░рд┐рдкреЛрд░реНрдЯ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИред рд▓реЗрдХрд┐рди рд╣рдорд╛рд░реЗ рдкрд░реАрдХреНрд╖рдг рдмреНрд░рд╣реНрдорд╛рдВрдб рдореЗрдВ рдкреНрд░рд╡реЗрд╢ рдмрд┐рдВрджреБ рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдХреНрдпрд╛?
рдЖрд╡рд╢реНрдпрдХрддрд╛рдПрдБ, рд╡реЗ рд╡рд┐рдирд┐рд░реНрджреЗрд╢ рд╣реИрдВ, рдкрд░рд┐рдпреЛрдЬрдирд╛ рдбреЗрд╡рд▓рдкрд░реНрд╕ рдиреЗ рдкрд░реАрдХреНрд╖рдг рдХреЗ рд░реВрдк рдореЗрдВ рд▓рд┐рдЦрдиреЗ рдХрд╛ рдлреИрд╕рд▓рд╛ рдХрд┐рдпрд╛ред рдкрд░рд┐рдгрд╛рдо рдПрдХ рджрд┐рд▓рдЪрд╕реНрдк рддрд╕реНрд╡реАрд░ рдереА - рдмреАрдбреАрдбреАред рдЗрд╕ рдкреНрд░рдХрд╛рд░, рдХреЛрдЯрд▓рд┐рди, рд╕реНрдкреЗрдХ рдФрд░ рдЦрдЯрдк рдЕрдЦрд╛рдбрд╝реЗ рдореЗрдВ рджрд┐рдЦрд╛рдИ рджрд┐рдПред
рдЪреМрдХрд╕ рдкрд╛рдардХ рдкреВрдЫреЗрдЧрд╛ - рдареАрдХ рд╣реИ, рд▓реЗрдХрд┐рди рдкрд░реАрдХреНрд╖рдХ рдХрд╣рд╛рдВ рд╣реИрдВ?
рдкрд░реАрдХреНрд╖рдХреЛрдВ
рдПрдХ рдкрддреНрдерд░ рдХреЗ рд╕рд╛рде рджреЛ рдкрдХреНрд╖рд┐рдпреЛрдВ рдХреЛ рд╕рдорд╛рдкреНрдд рдХрд░рдиреЗ рдХреЗ рдмрд╛рдж, рд╡рд┐рдХрд╛рд╕ рдиреЗ рдЙрддреНрдкрд╛рдж рдкрд░реАрдХреНрд╖рдХ рдХреЛ рдЖрд╡рд╢реНрдпрдХрддрд╛рдУрдВ рдФрд░ рдСрдЯреЛрдЯреЗрд╕реНрдЯ рджреЛрдиреЛрдВ рдХреЛ рджрд┐рдпрд╛ред рддрдм рд╕реЗ, рдкрд░реАрдХреНрд╖рдХ рдиреЗ рдЖрд╡рд╢реНрдпрдХрддрд╛рдУрдВ рдХреЗ рдЕрдиреБрд╕рд╛рд░ рдкрд░реАрдХреНрд╖рдг рдХрд╡рд░реЗрдЬ рдХрд╛ рд╡рд┐рд╕реНрддрд╛рд░ рдХрд┐рдпрд╛ рд╣реИ, рдФрд░ рдбреЗрд╡рд▓рдкрд░реНрд╕ рдХреЗ рд╕рд╛рде рдорд┐рд▓рдХрд░ рдирдП рдкрд░реАрдХреНрд╖рдгреЛрдВ рдХрд╛ рд╕рдорд░реНрдерди рдХрд░рддрд╛ рд╣реИ рдФрд░ рдмрдирд╛рддрд╛ рд╣реИред
"рдпрд╣ рд╣рдореЗрд╢рд╛ рдХреЗ рд▓рд┐рдП рдирд╣реАрдВ рдЪрд▓ рд╕рдХрддрд╛ рд╣реИ рдФрд░ рдкрд░реАрдХреНрд╖рдг рдкреНрд░рдХреНрд░рд┐рдпрд╛ рдХреЗ рд▓рд┐рдП рджреБрдЦрдж рд░реВрдк рд╕реЗ рд╕рдорд╛рдкреНрдд рдирд╣реАрдВ рд╣реЛрдирд╛ рдЪрд╛рд╣рд┐рдП!" - рдЬрдм рдЗрд╕ рддрд░рд╣ рдХреЗ рд╡рд┐рдЪрд╛рд░ рдХреЛ рд╕рд╣рдпреЛрдЧрд┐рдпреЛрдВ рджреНрд╡рд╛рд░рд╛ рджреМрд░рд╛ рдХрд┐рдпрд╛ рдЧрдпрд╛ рдерд╛, рддреЛ рдкрд░реАрдХреНрд╖рдг рд╡рд┐рднрд╛рдЧ рдХреЗ рд╕реЗрд╡рд╛ рд╡рд┐рднрд╛рдЧ рдХреА рдЯреАрдо рдиреЗ рдЦреЗрд▓ рдореЗрдВ рдкреНрд░рд╡реЗрд╢ рдХрд┐рдпрд╛ред рд╕реЗрд╡рд╛ рд╡рд┐рднрд╛рдЧ рдХреЛ рдХрд╛рд░реНрдп рдХрд╛ рд╕рд╛рдордирд╛ рдХрд░рдирд╛ рдкрдбрд╝рд╛: рдереЛрдбрд╝реЗ рд╕рдордп рдореЗрдВ рдХреЛрдЯрд▓рд┐рди рдХрд╛ рдЕрдзреНрдпрдпрди рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП, рддрд╛рдХрд┐ рдпрджрд┐ рдЖрд╡рд╢реНрдпрдХ рд╣реЛ, рддреЛ рдкрд░реАрдХреНрд╖рдгреЛрдВ рдХрд╛ рддреЗрдЬрд╝ рд╕рдорд░реНрдерди рд▓реЗред
рд╢реБрд░реБрдЖрдд рд╣реЛ рд░рд╣реА рд╣реИ
рд╕реЗрд╡рд╛ рд╡рд┐рднрд╛рдЧ рдореЗрдВ
IntelliJ IDEA рд╕реЗрд╡рд╛ рд╣реИ, рдФрд░ рдЪреВрдВрдХрд┐ рдХреЛрдЯрд▓рд┐рди
JVM рдХреЗ рд╢реАрд░реНрд╖ рдкрд░ рдЪрд▓рддрд╛ рд╣реИ рдФрд░
JetBrains рджреНрд╡рд╛рд░рд╛ рд╡рд┐рдХрд╕рд┐рдд рдХрд┐рдпрд╛ рдЧрдпрд╛ рдерд╛, рдЗрд╕рд▓рд┐рдП рдХреЛрдб рд▓рд┐рдЦрдиреЗ рдХреЗ рд▓рд┐рдП рдХреБрдЫ рднреА рдЕрддрд┐рд░рд┐рдХреНрдд рд╕реНрдерд╛рдкрд┐рдд рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рдирд╣реАрдВ рдереАред
рд╕реНрдкрд╖реНрдЯ рдХрд╛рд░рдгреЛрдВ рд╕реЗ, рд╣рдо рд╕реНрд╡рдпрдВ рднрд╛рд╖рд╛ рд╕реАрдЦрдиреЗ рдХреА рдкреНрд░рдХреНрд░рд┐рдпрд╛ рдХреЛ рдЫреЛрдбрд╝ рджреЗрдВрдЧреЗред
рдкрд╣рд▓реА рдЪреАрдЬ рдЬрд┐рд╕рдХреЗ рд╕рд╛рде рд╢реБрд░реВ рдХрд┐рдпрд╛ рдЧрдпрд╛ рдерд╛, рд░рд┐рдкреЙрдЬрд┐рдЯрд░реА рдХреЛ рдХреНрд▓реЛрди рдХрд░ рд░рд╣рд╛ рдерд╛:
git clone https://gerrit.project.com/k/autotests
рддрдм рдкрд░рд┐рдпреЛрдЬрдирд╛ рдХреЛ рдЦреЛрд▓рд╛ рдЧрдпрд╛ рдерд╛ рдФрд░
рдЧреНрд░реЗрдбрд▓ рд╕реЗрдЯрд┐рдВрдЧреНрд╕
рдЖрдпрд╛рдд рдХреА рдЧрдИ рдереАрдВ:

рдкреВрд░реНрдг рд╕рдВрддреБрд╖реНрдЯрд┐ рдФрд░ рдЖрд░рд╛рдо рдХреЗ рд▓рд┐рдП (* рд╡рд╛рд╕реНрддрд╡ рдореЗрдВ, рдпрд╣ рдмрд╣реБрдд рдЬрд░реВрд░реА рд╣реИ), рд╕реНрдкреЗрдХ
рдкреНрд▓рдЧрдЗрди рд╕реНрдерд╛рдкрд┐рдд рдХрд┐рдпрд╛
рдЧрдпрд╛ рдерд╛:

рдЙрдиреНрд╣реЛрдВрдиреЗ рд╡рд┐рдХрд╛рд╕ рдХреЗ рдорд╛рд╣реМрд▓ рдореЗрдВ рдкрд░реАрдХреНрд╖рдгреЛрдВ рдХреА рд╢реБрд░реВрдЖрдд рд╕реБрдирд┐рд╢реНрдЪрд┐рдд рдХреА:

рдкрд╣рд▓рд╛ рдЪрд░рдг рдкреВрд░рд╛ рд╣реЛ рдЧрдпрд╛ рдерд╛, рдФрд░ рдпрд╣ рд╕рдордп рдерд╛ рдХрд┐ рд╡реЗ рд╕реНрд╡рдпрдВ рдкрд░реАрдХреНрд╖рдг рд▓рд┐рдЦрдирд╛ рд╢реБрд░реВ рдХрд░ рджреЗрдВред
рдкрд░реАрдХреНрд╖рдг
рд╕реЗрд╡рд╛ рд╡рд┐рднрд╛рдЧ рдХреЗ рдЕрдЪреНрдЫреЗ рд▓реЛрдЧ рдЗрд╕ рдпрд╛ рдЙрд╕ рдЙрддреНрдкрд╛рдж рд╕реЗ рд╕рдВрдмрдВрдзрд┐рдд рдирд╣реАрдВ рд╣реИрдВред рдпреЗ рд╡реЗ рдХрд░реНрдордЪрд╛рд░реА рд╣реИрдВ рдЬреЛ рдкреНрд░рдХреНрд░рд┐рдпрд╛ рдХреЗ рд╕рднреА рдЪрд░рдгреЛрдВ рд╕рд╣рд┐рдд рдкрд░рд┐рдпреЛрдЬрдирд╛ рдкрд░ рд╕реНрд╡рдЪрд╛рд▓рди рд╕реНрдерд╛рдкрд┐рдд рдХрд░рдиреЗ рдореЗрдВ рдорджрдж рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдЬрд▓реНрджреА рдореЗрдВ рд╣реИрдВ, рдФрд░ рдлрд┐рд░ рд╕рдорд░реНрдерди рдФрд░ рдХрдореАрд╢рди рдХреЗ рд▓рд┐рдП рдЙрддреНрдкрд╛рдж рдкрд░реАрдХреНрд╖рдХреЛрдВ рдХреЛ рдкрд░реАрдХреНрд╖рдг рдкрд╛рд╕ рдХрд░рддреЗ рд╣реИрдВред
рдФрд░ рдЬрдм рд╕реЗ рдкрд░реАрдХреНрд╖рдг рд╡рд┐рднрд╛рдЧ рдХреА рдЖрдВрддрд░рд┐рдХ рдЯреАрдореЛрдВ рдХреА рдмрд╛рддрдЪреАрдд рдПрдХ рд╕рдорд╛рди рддрд░реАрдХреЗ рд╕реЗ рдЖрдпреЛрдЬрд┐рдд рдХреА рдЬрд╛рддреА рд╣реИ, рддрдм рд╕реЗрд╡рд╛ рд╡рд┐рднрд╛рдЧ рдХрдо рд╕реЗ рдХрдо рдкреНрд░рд╡реЗрд╢ рдХрд░рдиреЗ рдХреА рд╕реБрд╡рд┐рдзрд╛ рдХреЗ рд▓рд┐рдП рдЖрд╡рд╢реНрдпрдХрддрд╛рдУрдВ рдХреЛ "рдкреВрдЫрддрд╛ рд╣реИ"ред
рдРрд╕рд╛ рд▓рдЧ рд╕рдХрддрд╛ рд╣реИ рдХрд┐ рдпрд╣ "рдХреЗ" рдХреЗ рдорд╛рдорд▓реЗ рдореЗрдВ рдПрдХ рдореГрдд рдЕрдВрдд рд╣реИред рд▓реЗрдХрд┐рди рд╡рд╣рд╛рдБ рдпрд╣ рдерд╛:
- рдЙрд╕ рд░рд┐рдкреЙрдЬрд┐рдЯрд░реА рддрдХ рдкрд╣реБрдВрдЪ рдкрдврд╝реЗрдВ рдЬрд╣рд╛рдВ рдкреНрд░реЛрдЬреЗрдХреНрдЯ рд╕реНрд░реЛрдд рд╕рдВрдЧреНрд░рд╣реАрдд рдХрд┐рдП рдЧрдП рдереЗ;
- рднрдВрдбрд╛рд░ рдХрд╛ рдХреНрд▓реЛрди;
- рдЙрдиреНрд╣реЛрдВрдиреЗ рдЬрд╛рд╡рд╛ рдореЗрдВ рд▓рд┐рдЦреЗ рд╕реЛрд░реНрд╕ рдХреЛрдбреНрд╕ рдХреЛ рдкрдврд╝рдХрд░ рдЙрддреНрдкрд╛рдж рдХреА рдХрд╛рд░реНрдпрдХреНрд╖рдорддрд╛ рдХрд╛ рдкрддрд╛ рд▓рдЧрд╛рдирд╛ рд╢реБрд░реВ рдХрд┐рдпрд╛ред
рдЖрдкрдиреЗ рдХреНрдпрд╛ рдкрдврд╝рд╛?
рд╡рд┐рдХрд╛рд╕ "рдХреЗ" рдиреЗ рдлреАрдЪрд░ рдХреЗ рд▓рд┐рдП рдкрд░реАрдХреНрд╖рдг рд▓рд┐рдЦрдиреЗ рдХреЗ рд▓рд┐рдП рдХрд╣рд╛, рдЬреЛ рдЖрдкрдХреЛ рдмрд┐рдХреНрд░реА рдХреЗ рд▓рд┐рдП рдЙрддреНрдкрд╛рджреЛрдВ рдХреЛ рдЬреЛрдбрд╝рдиреЗ, рдЕрдкрдбреЗрдЯ рдХрд░рдиреЗ рдФрд░ рд╣рдЯрд╛рдиреЗ рдХреА рдЕрдиреБрдорддрд┐ рджреЗрддрд╛ рд╣реИред рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди рдореЗрдВ рджреЛ рднрд╛рдЧ рд╢рд╛рдорд┐рд▓ рдереЗ: "рд╡реЗрдм" рдФрд░ "рдореЛрдмрд╛рдЗрд▓"ред
рд╡реЗрдм рдХреЗ рдорд╛рдорд▓реЗ рдореЗрдВ:- рдЙрддреНрдкрд╛рджреЛрдВ рдХреЛ рдЬреЛрдбрд╝рдиреЗ рдХреЗ рд▓рд┐рдП, рдПрдХ POST рдЕрдиреБрд░реЛрдз рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ, рдЬрд┐рд╕рдХреЗ рд╢рд░реАрд░ рдореЗрдВ рдбреЗрдЯрд╛ рдХреЗ рд╕рд╛рде JSON рд╣реИред
- рдЙрддреНрдкрд╛рджреЛрдВ рдХреЛ рдЕрдкрдбреЗрдЯ рдпрд╛ рд╕рдВрдкрд╛рджрд┐рдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП, рдПрдХ рдкреАрдпреВрдЯреА рдЕрдиреБрд░реЛрдз рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ, рдЬрд┐рд╕рдХреЗ рд╢рд░реАрд░ рдореЗрдВ рдкрд░рд┐рд╡рд░реНрддрд┐рдд рдбреЗрдЯрд╛ рдХреЗ рд╕рд╛рде JSON рд╣реЛрддрд╛ рд╣реИред
- рдорд╛рд▓ рд╣рдЯрд╛рдиреЗ рдХреЗ рд▓рд┐рдП, рдПрдХ DELETE рдЕрдиреБрд░реЛрдз рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ, рдЬрд┐рд╕рдХрд╛ рд╢рд░реАрд░ рдЦрд╛рд▓реА рд╣реИред
рдореЛрдмрд╛рдЗрд▓ рдХреЗ рдорд╛рдорд▓реЗ рдореЗрдВ:рдЙрддреНрдкрд╛рджреЛрдВ рдХреЛ рдЬреЛрдбрд╝рдиреЗ, рдЕрджреНрдпрддрди рдХрд░рдиреЗ рдФрд░ рд╣рдЯрд╛рдиреЗ рдХреЗ рд▓рд┐рдП, рдПрдХ POST рдЕрдиреБрд░реЛрдз рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ, рдЬрд┐рд╕рдХреЗ рд╢рд░реАрд░ рдореЗрдВ рдирд┐рд░реНрджрд┐рд╖реНрдЯ рдСрдкрд░реЗрд╢рди рдХреЗ рд▓рд┐рдП рдбреЗрдЯрд╛ рдХреЗ рд╕рд╛рде JSON рд╣реЛрддрд╛ рд╣реИред
рдпрд╛рдиреА JSON рдореЗрдВ рддреАрди рдиреЛрдб рд╣реИрдВ:
- "рдЬреЛрдбрд╝рд╛ рдЧрдпрд╛: рдЬреЛрдбрд╝рд╛ рдЙрддреНрдкрд╛рджреЛрдВ рдХреА рд╕реВрдЪреА,
- "рдирд┐рдХрд╛рд▓рд╛ рдЧрдпрд╛": рд╣рдЯрд╛рдП рдЧрдП рдЖрдЗрдЯрдореЛрдВ рдХреА рдПрдХ рд╕реВрдЪреА,
- "рдЕрджреНрдпрддрд┐рдд": рдЕрджреНрдпрддрди рдЙрддреНрдкрд╛рджреЛрдВ рдХреА рдПрдХ рд╕реВрдЪреАред
рдЖрдкрдиреЗ рдХреНрдпрд╛ рд▓рд┐рдЦрд╛?
рдкрд░реАрдХреНрд╖рдг рд╡рд┐рдирд┐рд░реНрджреЗрд╢реЛрдВ рд╡рд╛рд▓реЗ рдПрдХ рдкрд░реАрдХреНрд╖рдг рд╡рд░реНрдЧ рдХреЛ рдкрд╣рд▓реЗ рд╕реЗ рд╣реА рдмрдирд╛рдпрд╛ рдЧрдпрд╛ рдерд╛ рдФрд░ рдЗрд╕рдореЗрдВ рдкрд░реАрдХреНрд╖рдг рд╡рд┐рдзрд┐рдпрд╛рдБ (* рд╕реНрдкреЗрдХ рдореЗрдВ рдереЛрдбрд╝реА рдирд╣реАрдВ) рдереАрдВ, рдЗрд╕рд▓рд┐рдП рдЗрд╕рдХрд╛ рд╡рд┐рд╕реНрддрд╛рд░ рдХрд░рдирд╛ рдЖрд╡рд╢реНрдпрдХ рдерд╛ред
рд╡реЗрдм рдХреЗ рд▓рд┐рдПрд╕рдлрд▓ рдЙрддреНрдкрд╛рдж рдЬреЛрдбрд╝ рдХреЗ рд▓рд┐рдП рдкрд░реАрдХреНрд╖рдг:
- рдЖрдЗрдЯрдо рдЬреЛрдбрд╝реЗрдВ
- рдЬрд╛рдБрдЪ рд▓реЗрдВ рдХрд┐ рдЖрдЗрдЯрдо рдЬреЛрдбрд╝ рджрд┐рдпрд╛ рдЧрдпрд╛ рд╣реИред
- рдмрдирд╛рдП рдЧрдП рдЙрддреНрдкрд╛рдж рдХреЛ рд╣рдЯрд╛рдПрдВ (рдкреЛрд╕реНрдЯрдХрдВрдбрд┐рд╢рди)
рдХреЛрдб:
on("get changed since when goods added") { val goodsUpdateName: String = RandomStringUtils.randomAlphabetic(8) val date = Date.from(Instant.now()).time - 1 val goodsAdded = post(baseUrl + "goods/${user.storeId}", authHeader, json = dataToMap(goods.copy(name = goodsUpdateName))) it("should return the status code OK") { goodsAdded.statusCode.should.be.equal(OK) } val goodId = goodsAdded.jsonObject?.optLong("id") val goodsUpdates = get(baseUrl + "updates/goods/since/" + date, authHeader.plus("AppUID" to user.AppUID)) it("should return the status code OK") { goodsUpdates.statusCode.should.be.equal(OK) } val goodsInsert = goodsUpdates.jsonObject.getJSONArray("updated").toList() .map { it as JSONObject } .find { it.optLong("goodId") == goodId } it("should contain goods insert") { goodsInsert.should.be.not.`null` goodsInsert?.optString("name").should.be.equal(goodsUpdateName) } delete(baseUrl + "goods/${user.storeId}/$goodId", authHeader) }
рдорд╛рд▓ рдХреЛ рд╣рдЯрд╛рдиреЗ рдХреЗ рд▓рд┐рдП рд╕рдлрд▓ рдкрд░реАрдХреНрд╖рдг:
- рдЙрддреНрдкрд╛рдж рдЬреЛрдбрд╝реЗрдВ (рдкреВрд░реНрд╡ рд╢рд░реНрдд)
- рд╣рдо рдорд╛рд▓ рд╣рдЯрд╛рддреЗ рд╣реИрдВ
- рд╣рдо рдЬрд╛рдВрдЪрддреЗ рд╣реИрдВ рдХрд┐ рдЙрддреНрдкрд╛рдж рд╣рдЯрд╛ рджрд┐рдпрд╛ рдЧрдпрд╛ рд╣реИ
рдХреЛрдб:
on("get changed since when goods deleted") { val goodsUpdateName: String = RandomStringUtils.randomAlphabetic(8) val date = Date.from(Instant.now()).time - 1 val goodsAdded = post(baseUrl + "goods/${user.storeId}", authHeader, json = dataToMap(goods.copy(name = goodsUpdateName))) it("should return the status code OK") { goodsAdded.statusCode.should.be.equal(OK) } val goodId = goodsAdded.jsonObject?.optLong("id") val responseDelete = delete(baseUrl + "goods/${user.storeId}/$goodId", authHeader) it("should return the status code NO_CONTENT") { responseDelete.statusCode.should.be.equal(NO_CONTENT) } val goodsUpdates = get(baseUrl + "updates/goods/since/" + date, authHeader.plus("AppUID" to user.AppUID)) it("should contain goods deletes") { goodsUpdates.statusCode.should.be.equal(OK) goodsUpdates.jsonObject.getJSONArray("removed").toList() .map { it as Int } .find { it == goodId.toInt() } .should.be.not.`null` } }
рдЕрдирдзрд┐рдХреГрдд рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рджреНрд╡рд╛рд░рд╛ рдХреНрд╡реЗрд░реА рдирд┐рд╖реНрдкрд╛рджрди рдХреЗ рд▓рд┐рдП рдирдХрд╛рд░рд╛рддреНрдордХ рдкрд░реАрдХреНрд╖рдг
- рдЖрдЗрдЯрдо рдЬреЛрдбрд╝реЗрдВ
- рдкреНрд░рддрд┐рдХреНрд░рд┐рдпрд╛ рдХреА рд╕реНрдерд┐рддрд┐ рдХреА рдЬрд╛рдБрдЪ рдХрд░реЗрдВ
- рдПрдХ рдЙрддреНрдкрд╛рдж рдЬреЛрдбрд╝рдиреЗ рдХрд╛ рдЕрдиреБрд░реЛрдз рдПрдХ рдкреНрд░рд╛рдзрд┐рдХрд░рдг рд╣реЗрдбрд░ рдХреЗ рдмрд┐рдирд╛ рднреЗрдЬрд╛ рдЬрд╛рддрд╛ рд╣реИред рдЙрддреНрддрд░ 401 рдЕрдирдзрд┐рдХреГрдд рд╕реНрдерд┐рддрд┐ рдХреЗ рд╕рд╛рде рдЖрддрд╛ рд╣реИред
рдХреЛрдб:
on("get changed since when goods added without authorization") { val response = post(baseUrl + "goods/${user.storeId}", json = dataToMap(goods)) it("should contain an Unauthorized response status and an empty body") { response.statusCode.should.be.equal(UNAUTHORIZED) response.text.should.be.equal("") } }
рдореЛрдмрд╛рдЗрд▓ рдХреЗ рд▓рд┐рдПрдкреНрд░рддрд┐рдХреНрд░рд┐рдпрд╛ рд╢рд░реАрд░ рдФрд░ рдЕрдиреБрд░реЛрдз рдирд┐рдХрд╛рдп рдХреЗ рдЧрдарди рд╕реЗ рдиреЛрдб рдкреНрд░рд╛рдкреНрдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рд╣реЗрд▓реНрдкрд░ рдлрд╝рдВрдХреНрд╢рди рд▓рд┐рдЦреЗ рдЧрдП рдереЗред
рдХреЛрдб:
package com.qiwi.k.tests import com.fasterxml.jackson.databind.ObjectMapper import khttp.responses.Response import org.json.JSONObject val mapper = ObjectMapper() fun arrayAdded(n: Int): Array<GoodsUpdate> { return Array(n) { i -> GoodsUpdate() } } fun getGoodsIds(list: List<GoodsUpdate>): List<Long> { return Array(list.size) { i -> list[i].goodId }.toList() } fun getResult(response: Response): List<GoodsUpdate> { return mapper.readValue( response.jsonObject.getJSONArray("result").toString(), Array<GoodsUpdate>::class.java ).toList() } fun getCountryIdFromTheResult(response: Response): List<Int> { val listGoods = mapper.readValue( response.jsonObject.getJSONArray("result").toString(), Array<GoodsUpdate>::class.java ).toList() return Array(listGoods.size) { i -> listGoods[i].countryId }.toList() } fun getBody(added: Array<GoodsUpdate> = emptyArray(), removed: List<Long> = emptyList(), updated: List<GoodsUpdate> = emptyList()): JSONObject { return JSONObject( mapOf( "added" to added, "removed" to removed, "updated" to updated ) ) }
рд╕рдлрд▓ рдЙрддреНрдкрд╛рдж рдЬреЛрдбрд╝ рдХреЗ рд▓рд┐рдП рдкрд░реАрдХреНрд╖рдг
- рдЖрдЗрдЯрдо рдЬреЛрдбрд╝реЗрдВ
- рдЬрд╛рдБрдЪ рд▓реЗрдВ рдХрд┐ рдЖрдЗрдЯрдо рдЬреЛрдбрд╝ рджрд┐рдпрд╛ рдЧрдпрд╛ рд╣реИред
- рд╣рдо рдорд╛рд▓ рд╣рдЯрд╛рддреЗ рд╣реИрдВ (рдкреЛрд╕реНрдЯрдХрд╛рдВрдбрд┐рд╢рди)
рдХреЛрдб:
on("adding goods") { val respAdd = post(urlGoodsUpdate, authHeaderWithAppUID, json = getBody(added = arrayAdded(count))) val resultOfAdding = getResult(respAdd) it("should return the status code OK") { respAdd.statusCode.should.be.equal(OK) } it("should be equal to the size of the variable count") { resultOfAdding.should.be.size.equal(count) } post(urlGoodsUpdate, authHeaderWithAppUID, json = getBody(removed = getGoodsIds(resultOfAdding))) }
рд╕рдлрд▓ рдЙрддреНрдкрд╛рдж рдЕрджреНрдпрддрди рдХреЗ рд▓рд┐рдП рдкрд░реАрдХреНрд╖рдг рдХрд░реЗрдВ
- рдЙрддреНрдкрд╛рдж рдЬреЛрдбрд╝реЗрдВ (рдкреВрд░реНрд╡ рд╢рд░реНрдд)
- рд╣рдо рдорд╛рд▓ рдЕрджреНрдпрддрди рдХрд░рддреЗ рд╣реИрдВ
- рдЬрд╛рдБрдЪреЗрдВ рдХрд┐ рдЬреЛрдбрд╝рд╛ рдЧрдпрд╛ рдЖрдЗрдЯрдо рдЕрджреНрдпрддрди рдХрд┐рдпрд╛ рдЧрдпрд╛ рд╣реИред
- рд╣рдо рдорд╛рд▓ рд╣рдЯрд╛рддреЗ рд╣реИрдВ (рдкреЛрд╕реНрдЯрдХрд╛рдВрдбрд┐рд╢рди)
рдХреЛрдб:
on("updating goods") { val respAdd = post(urlGoodsUpdate, authHeaderWithAppUID, json = getBody(added = arrayAdded(count))) val resultOfAdding = getResult(respAdd) it("should return the status code respAdd OK") { respAdd.statusCode.should.be.equal(OK) } it("should be equal to the size of the variable count (resultOfAdding)") { resultOfAdding.should.be.size.equal(count) } val respUpdate = post(urlGoodsUpdate, authHeaderWithAppUID, json = getBody(updated = resultOfAdding.map { it.copy(countryId = REGION_77) }) ) it("should return the status code respUpdate OK") { respUpdate.statusCode.should.be.equal(OK) } it("should be equal to the size of the variable count (respUpdate)") { getResult(respUpdate).should.be.size.equal(count) } it("should be all elements are 77") { getCountryIdFromTheResult(respUpdate).should.be.all.elements(REGION_77) } post(urlGoodsUpdate, authHeaderWithAppUID, json = getBody(removed = getGoodsIds(resultOfAdding))) }
рдорд╛рд▓ рдХреЛ рд╣рдЯрд╛рдиреЗ рдХреЗ рд▓рд┐рдП рд╕рдлрд▓ рдкрд░реАрдХреНрд╖рдг:
- рдЙрддреНрдкрд╛рдж рдЬреЛрдбрд╝реЗрдВ (рдкреВрд░реНрд╡ рд╢рд░реНрдд)
- рд╣рдо рдорд╛рд▓ рд╣рдЯрд╛рддреЗ рд╣реИрдВ
- рд╣рдо рд╕рддреНрдпрд╛рдкрд┐рдд рдХрд░рддреЗ рд╣реИрдВ рдХрд┐ рдЬреЛрдбрд╝рд╛ рдЧрдпрд╛ рдЙрддреНрдкрд╛рдж рд╣рдЯрд╛ рджрд┐рдпрд╛ рдЧрдпрд╛ рд╣реИ
рдХреЛрдб:
on("deleting goods") { val respAdd = post(urlGoodsUpdate, authHeaderWithAppUID, json = getBody(added = arrayAdded(count))) val resultOfAdding = getResult(respAdd) it("should return the status code respAdd OK") { respAdd.statusCode.should.be.equal(OK) } it("should be equal to the size of the variable count") { resultOfAdding.should.be.size.equal(count) } val respRemoved = post(urlGoodsUpdate, authHeaderWithAppUID, json = getBody(removed = getGoodsIds(resultOfAdding)) ) it("should return the status code respRemoved OK") { respRemoved.statusCode.should.be.equal(OK) } it("should be empty") { getResult(respRemoved).should.be.empty } }
рдкрд░реАрдХреНрд╖рдгреЛрдВ рдХреЛ рд▓рд┐рдЦрдиреЗ рдХреЗ рдмрд╛рдж, рдХреЛрдб рдХреА рд╕рдореАрдХреНрд╖рд╛ рдХреЗ рдорд╛рдзреНрдпрдо рд╕реЗ рдЬрд╛рдирд╛ рдЖрд╡рд╢реНрдпрдХ рдерд╛ред
рд╕рдореАрдХреНрд╖рд╛
рдПрдХ рджрд░реНрдЬрди рд╕реЗ рдЕрдзрд┐рдХ рдХрдорд┐рдЯ, рджреЗрд╡ рдХреЗ рд╕рд╛рде рдмрд╣реБрдд рд╕реЗ рдкрддреНрд░рд╛рдЪрд╛рд░, рдордВрдЪреЛрдВ рдкрд░ рдЬрд╛рдХрд░, Google рдХреЗ рд╕рд╛рде рд╕рдВрд╡рд╛рдж рдХрд░рддреЗ рд╣реБрдПред рдФрд░ рдпрд╣рд╛рдБ рдкрд░рд┐рдгрд╛рдо рд╣реИред
рдХреЛрдб:
package com.qiwi.k.tests.catalog import тАж class GoodsUpdatesControllerSpec : WebSpek({ given("GoodsUpdatesController") { val OK = HttpResponseStatus.OK.code() val NO_CONTENT = HttpResponseStatus.NO_CONTENT.code() val UNAUTHORIZED = HttpResponseStatus.UNAUTHORIZED.code() val REGION_77 = 77 val auth = login(user) val accessToken = auth.tokenHead + auth.tokenTail val authHeader = mapOf("Authorization" to "Bearer $accessToken") val baseUrl = "http://test.qiwi.com/catalog/" val count = 2 val authHeaderWithAppUID = mapOf("Authorization" to "Bearer $accessToken", "AppUID" to user.AppUID) val urlGoodsUpdate = "http://test.qiwi.com/catalog/updates/goods/" on("get changes since") { val goodsName: String = goodsForUpdate.name + Random().nextInt(1000) val date = Date.from(Instant.now()).time - 1 put(baseUrl + "goods/${user.storeId}", authHeader, json = dataToMap(goodsForUpdate.copy(name = goodsName))) val goodsUpdates = get(baseUrl + "updates/goods/since/" + date, authHeader.plus("AppUID" to user.AppUID)) it("should contain goods updates") { val updates = goodsUpdates.jsonObject.getJSONArray("updated").toList() .map { it as JSONObject } .find { it.optLong("goodId") == goodsForUpdate.id } updates.should.be.not.`null` updates?.optString("name").should.be.equal(goodsName) } } on("get changed since when goods added") { val goodsUpdateName: String = RandomStringUtils.randomAlphabetic(8) val date = Date.from(Instant.now()).time - 1 val goodsAdded = post(baseUrl + "goods/${user.storeId}", authHeader, json = dataToMap(goods.copy(name = goodsUpdateName))) it("should return the status code OK") { goodsAdded.statusCode.should.be.equal(OK) } val goodId = goodsAdded.jsonObject?.optLong("id") val goodsUpdates = get(baseUrl + "updates/goods/since/" + date, authHeader.plus("AppUID" to user.AppUID)) it("should return the status code OK") { goodsUpdates.statusCode.should.be.equal(OK) } val goodsInsert = goodsUpdates.jsonObject.getJSONArray("updated").toList() .map { it as JSONObject } .find { it.optLong("goodId") == goodId } it("should contain goods insert") { goodsInsert.should.be.not.`null` goodsInsert?.optString("name").should.be.equal(goodsUpdateName) } delete(baseUrl + "goods/${user.storeId}/$goodId", authHeader) } on("get changed since when goods deleted") { val goodsUpdateName: String = RandomStringUtils.randomAlphabetic(8) val date = Date.from(Instant.now()).time - 1 val goodsAdded = post(baseUrl + "goods/${user.storeId}", authHeader, json = dataToMap(goods.copy(name = goodsUpdateName))) it("should return the status code OK") { goodsAdded.statusCode.should.be.equal(OK) } val goodId = goodsAdded.jsonObject?.optLong("id") val responseDelete = delete(baseUrl + "goods/${user.storeId}/$goodId", authHeader) it("should return the status code NO_CONTENT") { responseDelete.statusCode.should.be.equal(NO_CONTENT) } val goodsUpdates = get(baseUrl + "updates/goods/since/" + date, authHeader.plus("AppUID" to user.AppUID)) it("should contain goods deletes") { goodsUpdates.statusCode.should.be.equal(OK) goodsUpdates.jsonObject.getJSONArray("removed").toList() .map { it as Int } .find { it == goodId.toInt() } .should.be.not.`null` } } on("get changed since when goods added without authorization") { val response = post(baseUrl + "goods/${user.storeId}", json = dataToMap(goods)) it("should contain an Unauthorized response status and an empty body") { response.statusCode.should.be.equal(UNAUTHORIZED) response.text.should.be.equal("") } } on("adding goods") { val respAdd = post(urlGoodsUpdate, authHeaderWithAppUID, json = getBody(added = arrayAdded(count))) val resultOfAdding = getResult(respAdd) it("should return the status code OK") { respAdd.statusCode.should.be.equal(OK) } it("should be equal to the size of the variable count") { resultOfAdding.should.be.size.equal(count) } post(urlGoodsUpdate, authHeaderWithAppUID, json = getBody(removed = getGoodsIds(resultOfAdding))) } on("updating goods") { val respAdd = post(urlGoodsUpdate, authHeaderWithAppUID, json = getBody(added = arrayAdded(count))) val resultOfAdding = getResult(respAdd) it("should return the status code respAdd OK") { respAdd.statusCode.should.be.equal(OK) } it("should be equal to the size of the variable count (resultOfAdding)") { resultOfAdding.should.be.size.equal(count) } val respUpdate = post(urlGoodsUpdate, authHeaderWithAppUID, json = getBody(updated = resultOfAdding.map { it.copy(countryId = REGION_77) }) ) it("should return the status code respUpdate OK") { respUpdate.statusCode.should.be.equal(OK) } it("should be equal to the size of the variable count (respUpdate)") { getResult(respUpdate).should.be.size.equal(count) } it("should be all elements are 77") { getCountryIdFromTheResult(respUpdate).should.be.all.elements(REGION_77) } post(urlGoodsUpdate, authHeaderWithAppUID, json = getBody(removed = getGoodsIds(resultOfAdding))) } on("deleting goods") { val respAdd = post(urlGoodsUpdate, authHeaderWithAppUID, json = getBody(added = arrayAdded(count))) val resultOfAdding = getResult(respAdd) it("should return the status code respAdd OK") { respAdd.statusCode.should.be.equal(OK) } it("should be equal to the size of the variable count") { resultOfAdding.should.be.size.equal(count) } val respRemoved = post(urlGoodsUpdate, authHeaderWithAppUID, json = getBody(removed = getGoodsIds(resultOfAdding)) ) it("should return the status code respRemoved OK") { respRemoved.statusCode.should.be.equal(OK) } it("should be empty") { getResult(respRemoved).should.be.empty } } } })
рдкрд░рд┐рдгрд╛рдо
рдХреЛрдб рд╣реА, рднрд╛рд╖рд╛ рдХреМрд╢рд▓ рдФрд░ рдврд╛рдВрдЪреЗ рдХрд╛ рдЬреНрдЮрд╛рди рдПрдХрджрдо рд╕рд╣реА рд╣реИ, рд▓реЗрдХрд┐рди рд╢реБрд░реБрдЖрдд рдЖрдорддреМрд░ рдкрд░ рдЦрд░рд╛рдм рдирд╣реАрдВ рд╣реЛрддреА рд╣реИред
рдЬрдм рдореИрдВ рдХреЛрдЯрд▓рд┐рди рд╕реЗ рдорд┐рд▓рд╛, рддреЛ рдореБрдЭреЗ рд▓рдЧ рд░рд╣рд╛ рдерд╛ рдХрд┐ рд╡рд╣ рдЬрд╛рд╡рд╛ рдореЗрдВ рд╕рд┐рдВрдЯреИрдХреНрдЯрд┐рдХ рдЪреАрдиреА рд╣реИред рдФрд░ рдЖрддреНрдорд╛ рдХреЗ рд╕рднреА рддрдВрддреБрдУрдВ рдХреЗ рд╕рд╛рде рдХреЛрдб рд▓рд┐рдЦрддреЗ рд╕рдордп, рдореИрдВ рд╢рдмреНрджреЛрдВ рдХреЛ рдорд╣рд╕реВрд╕ рдХрд░рдиреЗ рдореЗрдВ рдХрд╛рдордпрд╛рдм рд░рд╣рд╛: "рдЬрд╛рд╡рд╛ рдХреЗ рд╕рд╛рде рдкреВрд░реА рддрд░рд╣ рд╕реЗ рд╕рдВрдЧрдд"ред
рд╕реНрдкреЗрдХ, рдЬреЛ рд╡рд┐рдирд┐рд░реНрджреЗрд╢реЛрдВ рдХрд╛ рд╡рд░реНрдгрди рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рд╕рд░рд▓ рднрд╛рд╖рд╛ рдирд┐рд░реНрдорд╛рдг рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддрд╛ рд╣реИ, рдкрд░реАрдХреНрд╖рдг рд╡рд┐рдзрд┐рдпреЛрдВ рдХрд╛ рдПрдХ рдкреВрд░рд╛ рдкреВрд▓ рдкреНрд░рджрд╛рди рдХрд░рддрд╛ рд╣реИред рдпрд╛рдиреА рдЯреЗрд╕реНрдЯ рдлреНрд░реЗрдорд╡рд░реНрдХ рд╕реЗ рд╡реЗ рдЙрд╕рд╕реЗ рдЬреЛ рдЪрд╛рд╣рддреЗ рд╣реИрдВ, рджреЗрддреЗ рд╣реИрдВред
рдХреБрд▓ - рдорд╛рд╕реНрдЯрд░ рдореЗрдВ рд╕рднреА рдкрд░реАрдХреНрд╖рдгред рд╕рдм рдХреБрдЫ рдХрд╛рдо рдХрд░ рдЧрдпрд╛, рдФрд░ рд╕реЗрд╡рд╛ рд╡рд┐рднрд╛рдЧ рдЕрдм рдпрд╣ рд╕реБрдирд┐рд╢реНрдЪрд┐рдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдЬрд╛рдирддрд╛ рд╣реИ рдХрд┐ рдпрд╣ рдореБрд╢реНрдХрд┐рд▓ рд╕рдордп рдореЗрдВ рдХреЗ рд╕реЗ рд╕рд╣рдпреЛрдЧрд┐рдпреЛрдВ рдХрд╛ рд╕рдорд░реНрдерди рдХрд░рдиреЗ рдореЗрдВ рд╕рдХреНрд╖рдо рд╣реЛрдЧрд╛ред