Мои юнит-тесты хороши?


Это первый раз, когда я написал юнит-тесты. Я тестирую код, который я уже писал и хотел бы переехать в ТДД однажды мне удалось сделать блоки, написанные за все, что уже есть в моем приложении.

Просто хотел убедиться, что тесты, которые я написал хорошо выглядеть, или если есть другой подход, я должен быть приняты. Это в CakePHP 2.0

<?php
App::uses('Player', 'Model');

class PlayerTestCase extends CakeTestCase {
public $fixtures = array('app.player', 'app.club', 'app.position', 'app.stat', 'app.selection', 'app.period', 'app.league', 'app.draft', 'app.team');

public function setup() {
    parent::setUp();
    $this->Player = ClassRegistry::init('Player');
}

/**
 * testGetPlayers method
 *
 * @return void
 */ 
function testGetPlayers() {

    //Specific Player, All Stats, No Position Exclusion 
    $result = $this->Player->GetPlayers(11, 'all', null);
    $expected = array(
            'Player' => array ('id' => 11, 'name' => 'Forward 2', 'status' => 'doubtful', 'note' => '', 'club_id' => '2', 'position_id' => '4'),
            'Club' => array ('id' => 2, 'name' => 'Club 2', 'abbreviation' => 'clb2'),
            'Position' => array ('id' => 4, 'name' => 'Forward', 'abbreviation' => 'fw', 'min' => 1, 'max' => 3, 'need' => 2, 'db_abbr' => 'fw'),
            'Stat' => array (
                array ('id' => 11, 'rank' => 11, 'goals' => 0, 'saves' => 0, 'penaltysaves' => 0, 'assists' => 0, 'cleansheet' => 0, 'redcard' => 0, 'yellowcard' => 0, 'foulsconc' => 0, 'foulswon' => 0, 'tackleslost' => 0, 'tackleswon' => 0, 'shotontarget' => 0, 'totalshot' => 0, 'appearances' => 0, 'attcreated' => 0, 'totalpasses' => 0, 'accpasses' => 0, 'minutesplayed' => 0, 'conceded' => 0, 'player_id' => '11', 'team_id' => 0, 'period_id' => '1'),
                array ('id' => 23, 'rank' => 11, 'goals' => 0, 'saves' => 0, 'penaltysaves' => 0, 'assists' => 0, 'cleansheet' => 0, 'redcard' => 0, 'yellowcard' => 0, 'foulsconc' => 0, 'foulswon' => 0, 'tackleslost' => 0, 'tackleswon' => 0, 'shotontarget' => 0, 'totalshot' => 0, 'appearances' => 0, 'attcreated' => 0, 'totalpasses' => 0, 'accpasses' => 0, 'minutesplayed' => 0, 'conceded' => 0, 'player_id' => '11', 'team_id' => 0, 'period_id' => '2')
            )
    );
    $this->assertEquals($expected, $result);    

    //Specific Player, No Stats, No Position Exclusion
    $result = $this->Player->GetPlayers(10, false, null);       
    $expected = array(
            'Player' => array ('id' => 10, 'name' => 'Forward 1', 'status' => 'available', 'note' => '', 'club_id' => '1', 'position_id' => '4'),
            'Club' => array ('id' => 1, 'name' => 'Club 1', 'abbreviation' => 'clb1'),
            'Position' => array ('id' => 4, 'name' => 'Forward', 'abbreviation' => 'fw', 'min' => 1, 'max' => 3, 'need' => 2, 'db_abbr' => 'fw')
    );
    $this->assertEquals($expected, $result);    

    //No Specific Player, No Stats, Position Exclusion (Array)
    $result = $this->Player->GetPlayers(null, false, array('def', 'mid', 'fw'));        
    $expected = array(
        array(
            'Player' => array ('id' => 1, 'name' => 'Goalkeeper 1', 'status' => 'available', 'note' => '', 'club_id' => '1', 'position_id' => '1'),
            'Club' => array ('id' => 1, 'name' => 'Club 1', 'abbreviation' => 'clb1'),
            'Position' => array ('id' => 1, 'name' => 'Goalkeeper', 'abbreviation' => 'gk', 'min' => 1, 'max' => 1, 'need' => 1, 'db_abbr' => 'gk')
            ),
        array(
            'Player' => array ('id' => 2, 'name' => 'Goalkeeper 2', 'status' => 'doubtful', 'note' => '', 'club_id' => '2', 'position_id' => '1'),
            'Club' => array ('id' => 2, 'name' => 'Club 2', 'abbreviation' => 'clb2'),
            'Position' => array ('id' => 1, 'name' => 'Goalkeeper', 'abbreviation' => 'gk', 'min' => 1, 'max' => 1, 'need' => 1, 'db_abbr' => 'gk')
            ),
        array(
            'Player' => array ('id' => 3, 'name' => 'Goalkeeper 3', 'status' => 'unavailable', 'note' => '', 'club_id' => '3', 'position_id' => '1'),
            'Club' => array ('id' => 3, 'name' => 'Club 3', 'abbreviation' => 'clb3'),
            'Position' => array ('id' => 1, 'name' => 'Goalkeeper', 'abbreviation' => 'gk', 'min' => 1, 'max' => 1, 'need' => 1, 'db_abbr' => 'gk')
            )
    );
    $this->assertEquals($expected, $result);    

    //No Specific Player, Default Stats, Position Exclusion (String)
    $result = $this->Player->GetPlayers(null, true, 'gk');      
    $expected = array(
        array(
            'Player' => array ('id' => 4, 'name' => 'Defender 1', 'status' => 'available', 'note' => '', 'club_id' => '1', 'position_id' => '2'),
            'Club' => array ('id' => 1, 'name' => 'Club 1', 'abbreviation' => 'clb1'),
            'Position' => array ('id' => 2, 'name' => 'Defender', 'abbreviation' => 'def', 'min' => 3, 'max' => 5, 'need' => 4, 'db_abbr' => 'def'),
            'Stat' => array ('id' => 4, 'rank' => 4, 'goals' => 0, 'saves' => 0, 'penaltysaves' => 0, 'assists' => 0, 'cleansheet' => 0, 'redcard' => 0, 'yellowcard' => 0, 'foulsconc' => 0, 'foulswon' => 0, 'tackleslost' => 0, 'tackleswon' => 0, 'shotontarget' => 0, 'totalshot' => 0, 'appearances' => 0, 'attcreated' => 0, 'totalpasses' => 0, 'accpasses' => 0, 'minutesplayed' => 0, 'conceded' => 0, 'player_id' => '4', 'team_id' => 0, 'period_id' => '1')
            ),
        array(
            'Player' => array ('id' => 5, 'name' => 'Defender 2', 'status' => 'doubtful', 'note' => '', 'club_id' => '2', 'position_id' => '2'),
            'Club' => array ('id' => 2, 'name' => 'Club 2', 'abbreviation' => 'clb2'),
            'Position' => array ('id' => 2, 'name' => 'Defender', 'abbreviation' => 'def', 'min' => 3, 'max' => 5, 'need' => 4, 'db_abbr' => 'def'),
            'Stat' => array ('id' => 5, 'rank' => 5, 'goals' => 0, 'saves' => 0, 'penaltysaves' => 0, 'assists' => 0, 'cleansheet' => 0, 'redcard' => 0, 'yellowcard' => 0, 'foulsconc' => 0, 'foulswon' => 0, 'tackleslost' => 0, 'tackleswon' => 0, 'shotontarget' => 0, 'totalshot' => 0, 'appearances' => 0, 'attcreated' => 0, 'totalpasses' => 0, 'accpasses' => 0, 'minutesplayed' => 0, 'conceded' => 0, 'player_id' => '5', 'team_id' => 0, 'period_id' => '1')
            ),
        array(
            'Player' => array ('id' => 6, 'name' => 'Defender 3', 'status' => 'unavailable', 'note' => '', 'club_id' => '3', 'position_id' => '2'),
            'Club' => array ('id' => 3, 'name' => 'Club 3', 'abbreviation' => 'clb3'),
            'Position' => array ('id' => 2, 'name' => 'Defender', 'abbreviation' => 'def', 'min' => 3, 'max' => 5, 'need' => 4, 'db_abbr' => 'def'),
            'Stat' => array ('id' => 6, 'rank' => 6, 'goals' => 0, 'saves' => 0, 'penaltysaves' => 0, 'assists' => 0, 'cleansheet' => 0, 'redcard' => 0, 'yellowcard' => 0, 'foulsconc' => 0, 'foulswon' => 0, 'tackleslost' => 0, 'tackleswon' => 0, 'shotontarget' => 0, 'totalshot' => 0, 'appearances' => 0, 'attcreated' => 0, 'totalpasses' => 0, 'accpasses' => 0, 'minutesplayed' => 0, 'conceded' => 0, 'player_id' => '6', 'team_id' => 0, 'period_id' => '1')
            ),
        array(
            'Player' => array ('id' => 7, 'name' => 'Midfielder 1', 'status' => 'available', 'note' => '', 'club_id' => '1', 'position_id' => '3'),
            'Club' => array ('id' => 1, 'name' => 'Club 1', 'abbreviation' => 'clb1'),
            'Position' => array ('id' => 3, 'name' => 'Midfielder', 'abbreviation' => 'mid', 'min' => 2, 'max' => 5, 'need' => 4, 'db_abbr' => 'mid'),
            'Stat' => array ('id' => 7, 'rank' => 7, 'goals' => 0, 'saves' => 0, 'penaltysaves' => 0, 'assists' => 0, 'cleansheet' => 0, 'redcard' => 0, 'yellowcard' => 0, 'foulsconc' => 0, 'foulswon' => 0, 'tackleslost' => 0, 'tackleswon' => 0, 'shotontarget' => 0, 'totalshot' => 0, 'appearances' => 0, 'attcreated' => 0, 'totalpasses' => 0, 'accpasses' => 0, 'minutesplayed' => 0, 'conceded' => 0, 'player_id' => '7', 'team_id' => 0, 'period_id' => '1')
            ),
        array(
            'Player' => array ('id' => 8, 'name' => 'Midfielder 2', 'status' => 'doubtful', 'note' => '', 'club_id' => '2', 'position_id' => '3'),
            'Club' => array ('id' => 2, 'name' => 'Club 2', 'abbreviation' => 'clb2'),
            'Position' => array ('id' => 3, 'name' => 'Midfielder', 'abbreviation' => 'mid', 'min' => 2, 'max' => 5, 'need' => 4, 'db_abbr' => 'mid'),
            'Stat' => array ('id' => 8, 'rank' => 8, 'goals' => 0, 'saves' => 0, 'penaltysaves' => 0, 'assists' => 0, 'cleansheet' => 0, 'redcard' => 0, 'yellowcard' => 0, 'foulsconc' => 0, 'foulswon' => 0, 'tackleslost' => 0, 'tackleswon' => 0, 'shotontarget' => 0, 'totalshot' => 0, 'appearances' => 0, 'attcreated' => 0, 'totalpasses' => 0, 'accpasses' => 0, 'minutesplayed' => 0, 'conceded' => 0, 'player_id' => '8', 'team_id' => 0, 'period_id' => '1')
            ),
        array(
            'Player' => array ('id' => 9, 'name' => 'Midfielder 3', 'status' => 'unavailable', 'note' => '', 'club_id' => '3', 'position_id' => '3'),
            'Club' => array ('id' => 3, 'name' => 'Club 3', 'abbreviation' => 'clb3'),
            'Position' => array ('id' => 3, 'name' => 'Midfielder', 'abbreviation' => 'mid', 'min' => 2, 'max' => 5, 'need' => 4, 'db_abbr' => 'mid'),
            'Stat' => array ('id' => 9, 'rank' => 9, 'goals' => 0, 'saves' => 0, 'penaltysaves' => 0, 'assists' => 0, 'cleansheet' => 0, 'redcard' => 0, 'yellowcard' => 0, 'foulsconc' => 0, 'foulswon' => 0, 'tackleslost' => 0, 'tackleswon' => 0, 'shotontarget' => 0, 'totalshot' => 0, 'appearances' => 0, 'attcreated' => 0, 'totalpasses' => 0, 'accpasses' => 0, 'minutesplayed' => 0, 'conceded' => 0, 'player_id' => '9', 'team_id' => 0, 'period_id' => '1')
            ),
        array(
            'Player' => array ('id' => 10, 'name' => 'Forward 1', 'status' => 'available', 'note' => '', 'club_id' => '1', 'position_id' => '4'),
            'Club' => array ('id' => 1, 'name' => 'Club 1', 'abbreviation' => 'clb1'),
            'Position' => array ('id' => 4, 'name' => 'Forward', 'abbreviation' => 'fw', 'min' => 1, 'max' => 3, 'need' => 2, 'db_abbr' => 'fw'),
            'Stat' => array ('id' => 10, 'rank' => 10, 'goals' => 0, 'saves' => 0, 'penaltysaves' => 0, 'assists' => 0, 'cleansheet' => 0, 'redcard' => 0, 'yellowcard' => 0, 'foulsconc' => 0, 'foulswon' => 0, 'tackleslost' => 0, 'tackleswon' => 0, 'shotontarget' => 0, 'totalshot' => 0, 'appearances' => 0, 'attcreated' => 0, 'totalpasses' => 0, 'accpasses' => 0, 'minutesplayed' => 0, 'conceded' => 0, 'player_id' => '10', 'team_id' => 0, 'period_id' => '1')
            ),
        array(
            'Player' => array ('id' => 11, 'name' => 'Forward 2', 'status' => 'doubtful', 'note' => '', 'club_id' => '2', 'position_id' => '4'),
            'Club' => array ('id' => 2, 'name' => 'Club 2', 'abbreviation' => 'clb2'),
            'Position' => array ('id' => 4, 'name' => 'Forward', 'abbreviation' => 'fw', 'min' => 1, 'max' => 3, 'need' => 2, 'db_abbr' => 'fw'),
            'Stat' => array ('id' => 11, 'rank' => 11, 'goals' => 0, 'saves' => 0, 'penaltysaves' => 0, 'assists' => 0, 'cleansheet' => 0, 'redcard' => 0, 'yellowcard' => 0, 'foulsconc' => 0, 'foulswon' => 0, 'tackleslost' => 0, 'tackleswon' => 0, 'shotontarget' => 0, 'totalshot' => 0, 'appearances' => 0, 'attcreated' => 0, 'totalpasses' => 0, 'accpasses' => 0, 'minutesplayed' => 0, 'conceded' => 0, 'player_id' => '11', 'team_id' => 0, 'period_id' => '1')
            ),
        array(
            'Player' => array ('id' => 12, 'name' => 'Forward 3', 'status' => 'unavailable', 'note' => '', 'club_id' => '3', 'position_id' => '4'),
            'Club' => array ('id' => 3, 'name' => 'Club 3', 'abbreviation' => 'clb3'),
            'Position' => array ('id' => 4, 'name' => 'Forward', 'abbreviation' => 'fw', 'min' => 1, 'max' => 3, 'need' => 2, 'db_abbr' => 'fw'),
            'Stat' => array ('id' => 12, 'rank' => 12, 'goals' => 0, 'saves' => 0, 'penaltysaves' => 0, 'assists' => 0, 'cleansheet' => 0, 'redcard' => 0, 'yellowcard' => 0, 'foulsconc' => 0, 'foulswon' => 0, 'tackleslost' => 0, 'tackleswon' => 0, 'shotontarget' => 0, 'totalshot' => 0, 'appearances' => 0, 'attcreated' => 0, 'totalpasses' => 0, 'accpasses' => 0, 'minutesplayed' => 0, 'conceded' => 0, 'player_id' => '12', 'team_id' => 0, 'period_id' => '1')
            )
    );
    $this->assertEquals($expected, $result);    

    //Specific Player, Default Stats, No Position Exclusion
    $result = $this->Player->GetPlayers(10, true, null);        
    $expected = array(
            'Player' => array ('id' => 10, 'name' => 'Forward 1', 'status' => 'available', 'note' => '', 'club_id' => '1', 'position_id' => '4'),
            'Club' => array ('id' => 1, 'name' => 'Club 1', 'abbreviation' => 'clb1'),
            'Position' => array ('id' => 4, 'name' => 'Forward', 'abbreviation' => 'fw', 'min' => 1, 'max' => 3, 'need' => 2, 'db_abbr' => 'fw'),
            'Stat' => array ('id' => 10, 'rank' => 10, 'goals' => 0, 'saves' => 0, 'penaltysaves' => 0, 'assists' => 0, 'cleansheet' => 0, 'redcard' => 0, 'yellowcard' => 0, 'foulsconc' => 0, 'foulswon' => 0, 'tackleslost' => 0, 'tackleswon' => 0, 'shotontarget' => 0, 'totalshot' => 0, 'appearances' => 0, 'attcreated' => 0, 'totalpasses' => 0, 'accpasses' => 0, 'minutesplayed' => 0, 'conceded' => 0, 'player_id' => '10', 'team_id' => 0, 'period_id' => '1')
    );
    $this->assertEquals($expected, $result);    

    //Specific Player, Specific Stats, No Position Exclusion
    $result = $this->Player->GetPlayers(10, 2, null);       
    $expected = array(
            'Player' => array ('id' => 10, 'name' => 'Forward 1', 'status' => 'available', 'note' => '', 'club_id' => '1', 'position_id' => '4'),
            'Club' => array ('id' => 1, 'name' => 'Club 1', 'abbreviation' => 'clb1'),
            'Position' => array ('id' => 4, 'name' => 'Forward', 'abbreviation' => 'fw', 'min' => 1, 'max' => 3, 'need' => 2, 'db_abbr' => 'fw'),
            'Stat' => array ('id' => 22, 'rank' => 10, 'goals' => 0, 'saves' => 0, 'penaltysaves' => 0, 'assists' => 0, 'cleansheet' => 0, 'redcard' => 0, 'yellowcard' => 0, 'foulsconc' => 0, 'foulswon' => 0, 'tackleslost' => 0, 'tackleswon' => 0, 'shotontarget' => 0, 'totalshot' => 0, 'appearances' => 0, 'attcreated' => 0, 'totalpasses' => 0, 'accpasses' => 0, 'minutesplayed' => 0, 'conceded' => 0, 'player_id' => '10', 'team_id' => 0, 'period_id' => '2')
    );
    $this->assertEquals($expected, $result);

    //Player That Doesn't Exist
    $result = $this->Player->GetPlayers(999999, true, null);
    $this->assertFalse($result);        

    //Stats That Don't Exist
    $result = $this->Player->GetPlayers(null, 9999999, null);
    $this->assertFalse($result);    

    //Filter All Positions
    $result = $this->Player->GetPlayers(null, 9999999, array('gk', 'def', 'mid', 'fw'));
    $this->assertFalse($result);

}

//GetAvailablePlayers($league_id = null, $get_stats = true, $top_ranked_only = false, $exclude_positions = null) {  

function testGetAvailablePlayers() {

    //Get The Top Ranked Available Player with Stats
    $result = $this->Player->GetAvailablePlayers(1, null, true, null);
    $expected = array(
        'Player' => array ('id' => 2, 'name' => 'Goalkeeper 2', 'status' => 'doubtful', 'note' => '', 'club_id' => '2', 'position_id' => '1'),
        'Club' => array ('id' => 2, 'name' => 'Club 2', 'abbreviation' => 'clb2'),
        'Position' => array ('id' => 1, 'name' => 'Goalkeeper', 'abbreviation' => 'gk', 'min' => 1, 'max' => 1, 'need' => 1, 'db_abbr' => 'gk'),
        'Stat' => array ('id' => 2, 'rank' => 2, 'goals' => 0, 'saves' => 0, 'penaltysaves' => 0, 'assists' => 0, 'cleansheet' => 0, 'redcard' => 0, 'yellowcard' => 0, 'foulsconc' => 0, 'foulswon' => 0, 'tackleslost' => 0, 'tackleswon' => 0, 'shotontarget' => 0, 'totalshot' => 0, 'appearances' => 0, 'attcreated' => 0, 'totalpasses' => 0, 'accpasses' => 0, 'minutesplayed' => 0, 'conceded' => 0, 'player_id' => '2', 'team_id' => 0, 'period_id' => '1'),
        'Selection' => array ('id' => '', 'drafted' => '', 'locked' => '', 'position_id' => '', 'league_id' => '', 'team_id' => '', 'player_id' => '', 'period_id' => '')
    );
    $this->assertEquals($expected, $result);

    //Get All Available Players with No Stats Filtered by Position
    $result = $this->Player->GetAvailablePlayers(1, false, null, array('def', 'mid', 'fw'));
    $expected = array(
        array( 
        'Player' => array ('id' => 2, 'name' => 'Goalkeeper 2', 'status' => 'doubtful', 'note' => '', 'club_id' => '2', 'position_id' => '1'),
        'Club' => array ('id' => 2, 'name' => 'Club 2', 'abbreviation' => 'clb2'),
        'Position' => array ('id' => 1, 'name' => 'Goalkeeper', 'abbreviation' => 'gk', 'min' => 1, 'max' => 1, 'need' => 1, 'db_abbr' => 'gk'),
        'Selection' => array ('id' => '', 'drafted' => '', 'locked' => '', 'position_id' => '', 'league_id' => '', 'team_id' => '', 'player_id' => '', 'period_id' => '')
        ), 
        array( 
        'Player' => array ('id' => 3, 'name' => 'Goalkeeper 3', 'status' => 'unavailable', 'note' => '', 'club_id' => '3', 'position_id' => '1'),
        'Club' => array ('id' => 3, 'name' => 'Club 3', 'abbreviation' => 'clb3'),
        'Position' => array ('id' => 1, 'name' => 'Goalkeeper', 'abbreviation' => 'gk', 'min' => 1, 'max' => 1, 'need' => 1, 'db_abbr' => 'gk'),
        'Selection' => array ('id' => '', 'drafted' => '', 'locked' => '', 'position_id' => '', 'league_id' => '', 'team_id' => '', 'player_id' => '', 'period_id' => '')
        ), 
    );
    $this->assertEquals($expected, $result);

    //Test With League That Doesn't Exist
    $result = $this->Player->GetAvailablePlayers(5);
    $this->assertFalse($result);

}

function testIsAvailable() { 
    $result = $this->Player->IsAvailable(1, 1);
    $this->assertFalse($result);

    $result = $this->Player->IsAvailable(2, 1);
    $this->assertTrue($result); 

    $result = $this->Player->IsAvailable(1, 999999);
    $this->assertFalse($result);        
}

}
?>


338
4
задан 30 октября 2011 в 02:10 Источник Поделиться
Комментарии
1 ответ

Прежде всего, я хотел создать отдельный способ для каждого assertEquals() вызова. Это помогает локализация дефекта. Если первые утверждают, выдает ошибку вы не представляете, что 2-го, 3-го и другие ОК или нет. Имея лишь один утверждают, звонок в метод испытания является хорошей практикой. Комментарии должны быть название этих методов. (Комментарий обычно это код запах.)

В $Ожидается, что массивы являются достаточно сложными. Если игрок класса сделать новое поле (например, Ник) вы, вероятно, придется изменить все свои тесты, которые могут быть огромная боль. Я предлагаю использовать пользовательские методы assert. Например, вместо

//Get All Available Players with No Stats Filtered by Position
$result = $this->Player->GetAvailablePlayers(1, false, null, array('def', 'mid', 'fw'));
$expected = array(...)
$this->assertEquals($expected, $result);

попробовать

function testGetAllAvailablePlayersWithNoStatsFilteredByPosition() {
$result = $this->Player->GetAvailablePlayers(1, false, null,
array('def', 'mid', 'fw'));
$this->assertPlayerCount("playerCount", 2, $result);
$this->assertPlayerIdEquals("player id 1", 2, $result[0]);
$this->assertPlayerIdEquals("player id 2", 3, $result[1]);
}

(Конечно, вы должны написать assertPlayerCount и assertPlayerIdEquals методов. Первая строка параметр является утверждение сообщение. Это полезно, если у вас есть более чем один утверждают, звонок в один тестовый метод.)

В этом тестовом классе можно использовать общий приспособление. Если это возможно, попробуйте использовать свежий приспособление с встроенной установки. От
Тест Стратегии Автоматизации, Три Основные Стратегии Приспособления:


Эта общая стратегия приспособление часто используется для улучшения исполнения
скорость тестов, которые используют стойкие свежее приспособление, но это приходит с
изрядное количество багажа. Эти испытания требуют использования одного из
приспособление строительных и рушить запуска моделей. Они также
включают тесты, которые взаимодействуют друг с другом, будь то дизайн или
следствие, и это часто приводит к неравномерной тестов (стр. X) и высокой
Расходы На Техническое Обслуживание Тест.

(Цитируемый текст ссылки, проверить их.)

Если у вас достаточно времени, стоит читать в xUnit тестирования модели книги. Читать просто (Часть I и Часть II). это тоже выгодно.

(Обратите внимание, что я не написал какого-либо кода PHP в последние несколько лет, таким образом, выборка кодов, наверное, не компилируется и т. д.)

4
ответ дан 30 октября 2011 в 06:10 Источник Поделиться