Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/php/268.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
PHP单元测试函数_Php_Database_Testing - Fatal编程技术网

PHP单元测试函数

PHP单元测试函数,php,database,testing,Php,Database,Testing,我试图测试这个功能,我一直在尝试不同的方法,但没有成功。有人有ide吗?我如何以其他方式测试它,或者告诉我测试类有什么问题(我的测试类在本页末尾) 这是我的测试类,我连接到一个数据库。我尝试使用我的函数“testcheckbrute()”将值16作为id号,然后尝试使用该函数 <?php include 'functions.php'; class Test extends PHPUnit_Extensions_Database_TestCase { function getCo

我试图测试这个功能,我一直在尝试不同的方法,但没有成功。有人有ide吗?我如何以其他方式测试它,或者告诉我测试类有什么问题(我的测试类在本页末尾)

这是我的测试类,我连接到一个数据库。我尝试使用我的函数“testcheckbrute()”将值16作为id号,然后尝试使用该函数

<?php


include 'functions.php';


class Test extends PHPUnit_Extensions_Database_TestCase {

function getConnection(){

$mysqli = new mysqli('xxxxx.xxx.xx.se', 'xxx_xxxxxxxx', 'xxxxxx', 'db_xxxxxxxx');

if($mysqli->connect_errno > 0){
    die('Unable to connect to database [' . $mysqli->connect_error . ']');
    }
}

function testcheckbrute(){

$mysqli = new mysqli('atlas.dsv.su.se', 'xxx_xxxxxxx8', 'xxxxx', 'xx_xxxxxx');

checkbrute(16, $mysqli);

}
function setUp(){

}
function getDataSet(){

}}


?>

我没有看到任何实际的测试(断言)

例如:

$chk = checkbrute(16, $mysqli);
$this->assertTrue($chk);
etc.
这些断言构成了测试

您可能需要通读以下内容:


此外,我不确定“不成功”是什么意思。

我没有看到任何实际的测试(断言)

例如:

$chk = checkbrute(16, $mysqli);
$this->assertTrue($chk);
etc.
这些断言构成了测试

您可能需要通读以下内容:


此外,我不确定“不成功”是什么意思。

首先,您提供的测试用例不是单元测试,它被称为集成测试,因为它取决于环境中可用的MySQL服务器

那么,我们将进行集成测试。为了使事情足够简单,我们没有深入研究复杂的测试用例类,下面是一个示例测试用例类,它是在考虑可用性的情况下编写的:

tests.php

<?php
require_once(__DIR__.'/code.php');
class BruteForceTests extends PHPUnit_Framework_TestCase 
{

    /** @test */
    public function NoLoginAttemptsNoBruteforce()
    {
        // Given empty dataset any random time will do
        $any_random_time = date('H:i');

        $this->assertFalse(
            $this->isUserTriedToBruteForce($any_random_time)
        );
    }

    /** @test */
    public function DoNotDetectBruteforceIfLessThanFiveLoginAttemptsInLastTwoHours()
    {
        $this->userLogged('5:34');
        $this->userLogged('4:05');

        $this->assertFalse(
            $this->isUserTriedToBruteForce('6:00')
        );
    }

    /** @test */
    public function DetectBruteforceIfMoreThanFiveLoginAttemptsInLastTwoHours()
    {
        $this->userLogged('4:36');
        $this->userLogged('4:23');
        $this->userLogged('4:00');
        $this->userLogged('3:40');
        $this->userLogged('3:15');
        $this->userLogged('3:01'); // ping! 6th login, just in time

        $this->assertTrue(
            $this->isUserTriedToBruteForce('5:00')
        );
    }

    //==================================================================== SETUP

    /** @var PDO */
    private $connection;

    /** @var PDOStatement */
    private $inserter;

    const DBNAME = 'test';
    const DBUSER = 'tester';
    const DBPASS = 'secret';
    const DBHOST = 'localhost';

    public function setUp()
    {
        $this->connection = new PDO(
            sprintf('mysql:host=%s;dbname=%s', self::DBHOST, self::DBNAME), 
            self::DBUSER, 
            self::DBPASS
        );
        $this->assertInstanceOf('PDO', $this->connection);

        // Cleaning after possible previous launch
        $this->connection->exec('delete from login_attempts');

        // Caching the insert statement for perfomance
        $this->inserter = $this->connection->prepare(
            'insert into login_attempts (`user_id`, `time`) values(:user_id, :timestamp)'
        );
        $this->assertInstanceOf('PDOStatement', $this->inserter);
    }

    //================================================================= FIXTURES

    // User ID of user we care about
    const USER_UNDER_TEST = 1;
    // User ID of user who is just the noise in the DB, and should be skipped by tests
    const SOME_OTHER_USER = 2;

    /**
     * Use this method to record login attempts of the user we care about
     * 
     * @param string $datetime Any date & time definition which `strtotime()` understands.
     */ 
    private function userLogged($datetime)
    {
        $this->logUserLogin(self::USER_UNDER_TEST, $datetime);
    }

    /**
     * Use this method to record login attempts of the user we do not care about,
     * to provide fuzziness to our tests
     *
     * @param string $datetime Any date & time definition which `strtotime()` understands.
     */ 
    private function anotherUserLogged($datetime)
    {
        $this->logUserLogin(self::SOME_OTHER_USER, $datetime);
    }

    /**
     * @param int $userid
     * @param string $datetime Human-readable representation of login time (and possibly date)
     */
    private function logUserLogin($userid, $datetime)
    {
        $mysql_timestamp = date('Y-m-d H:i:s', strtotime($datetime));
        $this->inserter->execute(
            array(
                ':user_id' => $userid,
                ':timestamp' => $mysql_timestamp
            )
        );
        $this->inserter->closeCursor();
    }

    //=================================================================== HELPERS

    /**
     * Helper to quickly imitate calling of our function under test 
     * with the ID of user we care about, clean connection of correct type and provided testing datetime.
     * You can call this helper with the human-readable datetime value, although function under test
     * expects the integer timestamp as an origin date.
     * 
     * @param string $datetime Any human-readable datetime value
     * @return bool The value of called function under test.
     */
    private function isUserTriedToBruteForce($datetime)
    {
        $connection = $this->tryGetMysqliConnection();
        $timestamp = strtotime($datetime);
        return wasTryingToBruteForce(self::USER_UNDER_TEST, $connection, $timestamp);
    }

    private function tryGetMysqliConnection()
    {
        $connection = new mysqli(self::DBHOST, self::DBUSER, self::DBPASS, self::DBNAME);
        $this->assertSame(0, $connection->connect_errno);
        $this->assertEquals("", $connection->connect_error);
        return $connection;
    }

}
<?php

/**
 * Checks whether user was trying to bruteforce the login.
 * Bruteforce is defined as 6 or more login attempts in last 2 hours from $now.
 * Default for $now is current time.
 * 
 * @param int $user_id ID of user in the DB
 * @param mysqli $connection Result of calling `new mysqli`
 * @param timestamp $now Base timestamp to count two hours from
 * @return bool Whether the $user_id tried to bruteforce login or not.
 */
function wasTryingToBruteForce($user_id, $connection, $now)
{
    if (!$now)
        $now = time();

    $two_hours_ago = $now - (2 * 60 * 60);
    $since = date('Y-m-d H:i:s', $two_hours_ago); // Checking records of login attempts for last 2 hours

    $stmt = $connection->prepare("SELECT time FROM login_attempts WHERE user_id = ? AND time > ?");

    if ($stmt) { 
        $stmt->bind_param('is', $user_id, $since); 
        // Execute the prepared query.
        $stmt->execute();
        $stmt->store_result();
        // If there has been more than 5 failed logins
        if ($stmt->num_rows > 5) {
            return true;
        } else {
            return false;
        }
    }
}
检查时间应提取到函数参数,以便通过自动方式测试函数,如下所示:

function wasTryingToBruteForce($user_id, $connection, $now)
{
    if (!$now)
        $now = time();
    //... rest of code ...
}
如您所见,我已将您的函数重命名为更清晰的名称

除此之外,我认为您在创建SQL查询时应该非常小心,并且永远不要通过使用参数绑定连接字符串来构造SQL查询。因此,初始代码的稍微清理版本如下所示(请注意,测试套件在第一行就需要它):

code.php

<?php
require_once(__DIR__.'/code.php');
class BruteForceTests extends PHPUnit_Framework_TestCase 
{

    /** @test */
    public function NoLoginAttemptsNoBruteforce()
    {
        // Given empty dataset any random time will do
        $any_random_time = date('H:i');

        $this->assertFalse(
            $this->isUserTriedToBruteForce($any_random_time)
        );
    }

    /** @test */
    public function DoNotDetectBruteforceIfLessThanFiveLoginAttemptsInLastTwoHours()
    {
        $this->userLogged('5:34');
        $this->userLogged('4:05');

        $this->assertFalse(
            $this->isUserTriedToBruteForce('6:00')
        );
    }

    /** @test */
    public function DetectBruteforceIfMoreThanFiveLoginAttemptsInLastTwoHours()
    {
        $this->userLogged('4:36');
        $this->userLogged('4:23');
        $this->userLogged('4:00');
        $this->userLogged('3:40');
        $this->userLogged('3:15');
        $this->userLogged('3:01'); // ping! 6th login, just in time

        $this->assertTrue(
            $this->isUserTriedToBruteForce('5:00')
        );
    }

    //==================================================================== SETUP

    /** @var PDO */
    private $connection;

    /** @var PDOStatement */
    private $inserter;

    const DBNAME = 'test';
    const DBUSER = 'tester';
    const DBPASS = 'secret';
    const DBHOST = 'localhost';

    public function setUp()
    {
        $this->connection = new PDO(
            sprintf('mysql:host=%s;dbname=%s', self::DBHOST, self::DBNAME), 
            self::DBUSER, 
            self::DBPASS
        );
        $this->assertInstanceOf('PDO', $this->connection);

        // Cleaning after possible previous launch
        $this->connection->exec('delete from login_attempts');

        // Caching the insert statement for perfomance
        $this->inserter = $this->connection->prepare(
            'insert into login_attempts (`user_id`, `time`) values(:user_id, :timestamp)'
        );
        $this->assertInstanceOf('PDOStatement', $this->inserter);
    }

    //================================================================= FIXTURES

    // User ID of user we care about
    const USER_UNDER_TEST = 1;
    // User ID of user who is just the noise in the DB, and should be skipped by tests
    const SOME_OTHER_USER = 2;

    /**
     * Use this method to record login attempts of the user we care about
     * 
     * @param string $datetime Any date & time definition which `strtotime()` understands.
     */ 
    private function userLogged($datetime)
    {
        $this->logUserLogin(self::USER_UNDER_TEST, $datetime);
    }

    /**
     * Use this method to record login attempts of the user we do not care about,
     * to provide fuzziness to our tests
     *
     * @param string $datetime Any date & time definition which `strtotime()` understands.
     */ 
    private function anotherUserLogged($datetime)
    {
        $this->logUserLogin(self::SOME_OTHER_USER, $datetime);
    }

    /**
     * @param int $userid
     * @param string $datetime Human-readable representation of login time (and possibly date)
     */
    private function logUserLogin($userid, $datetime)
    {
        $mysql_timestamp = date('Y-m-d H:i:s', strtotime($datetime));
        $this->inserter->execute(
            array(
                ':user_id' => $userid,
                ':timestamp' => $mysql_timestamp
            )
        );
        $this->inserter->closeCursor();
    }

    //=================================================================== HELPERS

    /**
     * Helper to quickly imitate calling of our function under test 
     * with the ID of user we care about, clean connection of correct type and provided testing datetime.
     * You can call this helper with the human-readable datetime value, although function under test
     * expects the integer timestamp as an origin date.
     * 
     * @param string $datetime Any human-readable datetime value
     * @return bool The value of called function under test.
     */
    private function isUserTriedToBruteForce($datetime)
    {
        $connection = $this->tryGetMysqliConnection();
        $timestamp = strtotime($datetime);
        return wasTryingToBruteForce(self::USER_UNDER_TEST, $connection, $timestamp);
    }

    private function tryGetMysqliConnection()
    {
        $connection = new mysqli(self::DBHOST, self::DBUSER, self::DBPASS, self::DBNAME);
        $this->assertSame(0, $connection->connect_errno);
        $this->assertEquals("", $connection->connect_error);
        return $connection;
    }

}
<?php

/**
 * Checks whether user was trying to bruteforce the login.
 * Bruteforce is defined as 6 or more login attempts in last 2 hours from $now.
 * Default for $now is current time.
 * 
 * @param int $user_id ID of user in the DB
 * @param mysqli $connection Result of calling `new mysqli`
 * @param timestamp $now Base timestamp to count two hours from
 * @return bool Whether the $user_id tried to bruteforce login or not.
 */
function wasTryingToBruteForce($user_id, $connection, $now)
{
    if (!$now)
        $now = time();

    $two_hours_ago = $now - (2 * 60 * 60);
    $since = date('Y-m-d H:i:s', $two_hours_ago); // Checking records of login attempts for last 2 hours

    $stmt = $connection->prepare("SELECT time FROM login_attempts WHERE user_id = ? AND time > ?");

    if ($stmt) { 
        $stmt->bind_param('is', $user_id, $since); 
        // Execute the prepared query.
        $stmt->execute();
        $stmt->store_result();
        // If there has been more than 5 failed logins
        if ($stmt->num_rows > 5) {
            return true;
        } else {
            return false;
        }
    }
}
由于这是集成测试,因此需要可访问的MySQL实例,其中包含数据库,并定义了下表:

mysql> describe login_attempts;
+---------+------------------+------+-----+-------------------+----------------+
| Field   | Type             | Null | Key | Default           | Extra          |
+---------+------------------+------+-----+-------------------+----------------+
| id      | int(10) unsigned | NO   | PRI | NULL              | auto_increment |
| user_id | int(10) unsigned | YES  |     | NULL              |                |
| time    | timestamp        | NO   |     | CURRENT_TIMESTAMP |                |
+---------+------------------+------+-----+-------------------+----------------+
3 rows in set (0.00 sec)
考虑到被测函数的工作原理,这只是我个人的猜测,但我想你真的有这样的表


在运行测试之前,您必须在
tests.php
文件的“SETUP”部分配置
DB*
常量。

首先,您提供的测试用例不是单元测试,它被称为集成测试,因为它取决于环境中可用的MySQL服务器

那么,我们将进行集成测试。为了使事情足够简单,我们没有深入研究复杂的测试用例类,下面是一个示例测试用例类,它是在考虑可用性的情况下编写的:

tests.php

<?php
require_once(__DIR__.'/code.php');
class BruteForceTests extends PHPUnit_Framework_TestCase 
{

    /** @test */
    public function NoLoginAttemptsNoBruteforce()
    {
        // Given empty dataset any random time will do
        $any_random_time = date('H:i');

        $this->assertFalse(
            $this->isUserTriedToBruteForce($any_random_time)
        );
    }

    /** @test */
    public function DoNotDetectBruteforceIfLessThanFiveLoginAttemptsInLastTwoHours()
    {
        $this->userLogged('5:34');
        $this->userLogged('4:05');

        $this->assertFalse(
            $this->isUserTriedToBruteForce('6:00')
        );
    }

    /** @test */
    public function DetectBruteforceIfMoreThanFiveLoginAttemptsInLastTwoHours()
    {
        $this->userLogged('4:36');
        $this->userLogged('4:23');
        $this->userLogged('4:00');
        $this->userLogged('3:40');
        $this->userLogged('3:15');
        $this->userLogged('3:01'); // ping! 6th login, just in time

        $this->assertTrue(
            $this->isUserTriedToBruteForce('5:00')
        );
    }

    //==================================================================== SETUP

    /** @var PDO */
    private $connection;

    /** @var PDOStatement */
    private $inserter;

    const DBNAME = 'test';
    const DBUSER = 'tester';
    const DBPASS = 'secret';
    const DBHOST = 'localhost';

    public function setUp()
    {
        $this->connection = new PDO(
            sprintf('mysql:host=%s;dbname=%s', self::DBHOST, self::DBNAME), 
            self::DBUSER, 
            self::DBPASS
        );
        $this->assertInstanceOf('PDO', $this->connection);

        // Cleaning after possible previous launch
        $this->connection->exec('delete from login_attempts');

        // Caching the insert statement for perfomance
        $this->inserter = $this->connection->prepare(
            'insert into login_attempts (`user_id`, `time`) values(:user_id, :timestamp)'
        );
        $this->assertInstanceOf('PDOStatement', $this->inserter);
    }

    //================================================================= FIXTURES

    // User ID of user we care about
    const USER_UNDER_TEST = 1;
    // User ID of user who is just the noise in the DB, and should be skipped by tests
    const SOME_OTHER_USER = 2;

    /**
     * Use this method to record login attempts of the user we care about
     * 
     * @param string $datetime Any date & time definition which `strtotime()` understands.
     */ 
    private function userLogged($datetime)
    {
        $this->logUserLogin(self::USER_UNDER_TEST, $datetime);
    }

    /**
     * Use this method to record login attempts of the user we do not care about,
     * to provide fuzziness to our tests
     *
     * @param string $datetime Any date & time definition which `strtotime()` understands.
     */ 
    private function anotherUserLogged($datetime)
    {
        $this->logUserLogin(self::SOME_OTHER_USER, $datetime);
    }

    /**
     * @param int $userid
     * @param string $datetime Human-readable representation of login time (and possibly date)
     */
    private function logUserLogin($userid, $datetime)
    {
        $mysql_timestamp = date('Y-m-d H:i:s', strtotime($datetime));
        $this->inserter->execute(
            array(
                ':user_id' => $userid,
                ':timestamp' => $mysql_timestamp
            )
        );
        $this->inserter->closeCursor();
    }

    //=================================================================== HELPERS

    /**
     * Helper to quickly imitate calling of our function under test 
     * with the ID of user we care about, clean connection of correct type and provided testing datetime.
     * You can call this helper with the human-readable datetime value, although function under test
     * expects the integer timestamp as an origin date.
     * 
     * @param string $datetime Any human-readable datetime value
     * @return bool The value of called function under test.
     */
    private function isUserTriedToBruteForce($datetime)
    {
        $connection = $this->tryGetMysqliConnection();
        $timestamp = strtotime($datetime);
        return wasTryingToBruteForce(self::USER_UNDER_TEST, $connection, $timestamp);
    }

    private function tryGetMysqliConnection()
    {
        $connection = new mysqli(self::DBHOST, self::DBUSER, self::DBPASS, self::DBNAME);
        $this->assertSame(0, $connection->connect_errno);
        $this->assertEquals("", $connection->connect_error);
        return $connection;
    }

}
<?php

/**
 * Checks whether user was trying to bruteforce the login.
 * Bruteforce is defined as 6 or more login attempts in last 2 hours from $now.
 * Default for $now is current time.
 * 
 * @param int $user_id ID of user in the DB
 * @param mysqli $connection Result of calling `new mysqli`
 * @param timestamp $now Base timestamp to count two hours from
 * @return bool Whether the $user_id tried to bruteforce login or not.
 */
function wasTryingToBruteForce($user_id, $connection, $now)
{
    if (!$now)
        $now = time();

    $two_hours_ago = $now - (2 * 60 * 60);
    $since = date('Y-m-d H:i:s', $two_hours_ago); // Checking records of login attempts for last 2 hours

    $stmt = $connection->prepare("SELECT time FROM login_attempts WHERE user_id = ? AND time > ?");

    if ($stmt) { 
        $stmt->bind_param('is', $user_id, $since); 
        // Execute the prepared query.
        $stmt->execute();
        $stmt->store_result();
        // If there has been more than 5 failed logins
        if ($stmt->num_rows > 5) {
            return true;
        } else {
            return false;
        }
    }
}
检查时间应提取到函数参数,以便通过自动方式测试函数,如下所示:

function wasTryingToBruteForce($user_id, $connection, $now)
{
    if (!$now)
        $now = time();
    //... rest of code ...
}
如您所见,我已将您的函数重命名为更清晰的名称

除此之外,我认为您在创建SQL查询时应该非常小心,并且永远不要通过使用参数绑定连接字符串来构造SQL查询。因此,初始代码的稍微清理版本如下所示(请注意,测试套件在第一行就需要它):

code.php

<?php
require_once(__DIR__.'/code.php');
class BruteForceTests extends PHPUnit_Framework_TestCase 
{

    /** @test */
    public function NoLoginAttemptsNoBruteforce()
    {
        // Given empty dataset any random time will do
        $any_random_time = date('H:i');

        $this->assertFalse(
            $this->isUserTriedToBruteForce($any_random_time)
        );
    }

    /** @test */
    public function DoNotDetectBruteforceIfLessThanFiveLoginAttemptsInLastTwoHours()
    {
        $this->userLogged('5:34');
        $this->userLogged('4:05');

        $this->assertFalse(
            $this->isUserTriedToBruteForce('6:00')
        );
    }

    /** @test */
    public function DetectBruteforceIfMoreThanFiveLoginAttemptsInLastTwoHours()
    {
        $this->userLogged('4:36');
        $this->userLogged('4:23');
        $this->userLogged('4:00');
        $this->userLogged('3:40');
        $this->userLogged('3:15');
        $this->userLogged('3:01'); // ping! 6th login, just in time

        $this->assertTrue(
            $this->isUserTriedToBruteForce('5:00')
        );
    }

    //==================================================================== SETUP

    /** @var PDO */
    private $connection;

    /** @var PDOStatement */
    private $inserter;

    const DBNAME = 'test';
    const DBUSER = 'tester';
    const DBPASS = 'secret';
    const DBHOST = 'localhost';

    public function setUp()
    {
        $this->connection = new PDO(
            sprintf('mysql:host=%s;dbname=%s', self::DBHOST, self::DBNAME), 
            self::DBUSER, 
            self::DBPASS
        );
        $this->assertInstanceOf('PDO', $this->connection);

        // Cleaning after possible previous launch
        $this->connection->exec('delete from login_attempts');

        // Caching the insert statement for perfomance
        $this->inserter = $this->connection->prepare(
            'insert into login_attempts (`user_id`, `time`) values(:user_id, :timestamp)'
        );
        $this->assertInstanceOf('PDOStatement', $this->inserter);
    }

    //================================================================= FIXTURES

    // User ID of user we care about
    const USER_UNDER_TEST = 1;
    // User ID of user who is just the noise in the DB, and should be skipped by tests
    const SOME_OTHER_USER = 2;

    /**
     * Use this method to record login attempts of the user we care about
     * 
     * @param string $datetime Any date & time definition which `strtotime()` understands.
     */ 
    private function userLogged($datetime)
    {
        $this->logUserLogin(self::USER_UNDER_TEST, $datetime);
    }

    /**
     * Use this method to record login attempts of the user we do not care about,
     * to provide fuzziness to our tests
     *
     * @param string $datetime Any date & time definition which `strtotime()` understands.
     */ 
    private function anotherUserLogged($datetime)
    {
        $this->logUserLogin(self::SOME_OTHER_USER, $datetime);
    }

    /**
     * @param int $userid
     * @param string $datetime Human-readable representation of login time (and possibly date)
     */
    private function logUserLogin($userid, $datetime)
    {
        $mysql_timestamp = date('Y-m-d H:i:s', strtotime($datetime));
        $this->inserter->execute(
            array(
                ':user_id' => $userid,
                ':timestamp' => $mysql_timestamp
            )
        );
        $this->inserter->closeCursor();
    }

    //=================================================================== HELPERS

    /**
     * Helper to quickly imitate calling of our function under test 
     * with the ID of user we care about, clean connection of correct type and provided testing datetime.
     * You can call this helper with the human-readable datetime value, although function under test
     * expects the integer timestamp as an origin date.
     * 
     * @param string $datetime Any human-readable datetime value
     * @return bool The value of called function under test.
     */
    private function isUserTriedToBruteForce($datetime)
    {
        $connection = $this->tryGetMysqliConnection();
        $timestamp = strtotime($datetime);
        return wasTryingToBruteForce(self::USER_UNDER_TEST, $connection, $timestamp);
    }

    private function tryGetMysqliConnection()
    {
        $connection = new mysqli(self::DBHOST, self::DBUSER, self::DBPASS, self::DBNAME);
        $this->assertSame(0, $connection->connect_errno);
        $this->assertEquals("", $connection->connect_error);
        return $connection;
    }

}
<?php

/**
 * Checks whether user was trying to bruteforce the login.
 * Bruteforce is defined as 6 or more login attempts in last 2 hours from $now.
 * Default for $now is current time.
 * 
 * @param int $user_id ID of user in the DB
 * @param mysqli $connection Result of calling `new mysqli`
 * @param timestamp $now Base timestamp to count two hours from
 * @return bool Whether the $user_id tried to bruteforce login or not.
 */
function wasTryingToBruteForce($user_id, $connection, $now)
{
    if (!$now)
        $now = time();

    $two_hours_ago = $now - (2 * 60 * 60);
    $since = date('Y-m-d H:i:s', $two_hours_ago); // Checking records of login attempts for last 2 hours

    $stmt = $connection->prepare("SELECT time FROM login_attempts WHERE user_id = ? AND time > ?");

    if ($stmt) { 
        $stmt->bind_param('is', $user_id, $since); 
        // Execute the prepared query.
        $stmt->execute();
        $stmt->store_result();
        // If there has been more than 5 failed logins
        if ($stmt->num_rows > 5) {
            return true;
        } else {
            return false;
        }
    }
}
由于这是集成测试,因此需要可访问的MySQL实例,其中包含数据库,并定义了下表:

mysql> describe login_attempts;
+---------+------------------+------+-----+-------------------+----------------+
| Field   | Type             | Null | Key | Default           | Extra          |
+---------+------------------+------+-----+-------------------+----------------+
| id      | int(10) unsigned | NO   | PRI | NULL              | auto_increment |
| user_id | int(10) unsigned | YES  |     | NULL              |                |
| time    | timestamp        | NO   |     | CURRENT_TIMESTAMP |                |
+---------+------------------+------+-----+-------------------+----------------+
3 rows in set (0.00 sec)
考虑到被测函数的工作原理,这只是我个人的猜测,但我想你真的有这样的表


在运行测试之前,您必须在
tests.php
文件的“SETUP”部分中配置
DB*
常量。

使用succeed,我的意思是设置测试。如果你要测试,你会怎么做?我一直在看那个页面,但没能将它应用到我的代码中。你的问题确实不够具体,但当我开始设置单元测试时,我发现进入的障碍很难,所以我试图提供帮助。您应该从阅读我发布的链接开始。PHPUnit将测试断言($this->assert…),因此在我的示例中,我将测试checkbrute的返回值是否为true。如果是,则测试成功,如果不是,则测试失败。有很多东西可以断言,这取决于你想测试什么,这还不清楚。。但我发现很难将数据库中的数据与我想要比较的数据进行比较。假设我想将数据与ID 16进行比较。我想看看用户id 16的时间,就像我函数中的查询一样。我知道你应该这么做:$save=checkbrute(16,$mysqli)$此->资产包含($save,“16);但是当它开始比较时,它在数据库中找不到数据..它将16与一个空字符串进行比较。这是怎么回事?它没有找到id吗?您的函数没有返回查询结果,它看起来是返回true或false,因此在您的示例中,$save将是true或false。如果您想测试数据集,可以好的,我的意思是成功设置测试。如果你要测试它,你会怎么做?我一直在查看该页面,但无法将其应用到我的代码中。你的问题确实不够具体,但当我开始设置单元测试时,我发现进入的障碍很难,所以我试图提供帮助。你应该通过阅读我发布的链接启动。PHPUnit将测试断言($this->assert…),因此,在我的示例中,我正在测试checkbrute的返回值是否为真。如果测试成功,如果不是,测试失败。有很多东西需要断言,这取决于您尝试测试的内容,这一点并不清楚。我读过它。但我发现很难将数据库中的数据与我想要比较的数据进行比较。比方说我想将数据与ID 16进行比较。我想查看用户ID 16的时间,就像我函数中的查询一样。我知道你应该这样做:$save=checkbrute(16,$mysqli);$this->assertContains($save,“16”);但是当它开始比较时,在数据库中找不到数据。。