PHP TDD (Test Driven Development)

Nowadays almost all back-end developers are familiar with TDD. It has much more upsides and very little downsides once the actual classes and the test are in place. If you are just experimenting with your code and do not need it for a longer term, you may not need TDD in that case. TDD is actually essential if you want to maintain your code base for a long time.

So what does the Test Driven Development consist of? Well, there is the unit test that you write before you write most of any new code. Some of the code we have written actually are tested with integration tests. So for code that interacts with third party API or library/database etc, we write integration tests instead of unit tests.

Here are the different types of tests:

  1. Unit Testing: Unit testing is the lowest level of testing. It is usually testing methods inside a class. Unit tests do not interact with other classes directly, but instead with mocks. This makes unit tests isolated and easy to debug and refactor. The test loop would be a 3 steps: Fail, Pass, and Refactoring.
  2. Functional Testing: Functional testing is a type of testing that tests a whole feature which may call many other dependencies. Typically you would test a route for a correct response, or a Controller method that relates to a certain feature in the application. They are slower than integration tests as they require a lot more dependencies.
  3. Integration Testing: Integration testing requires more than one class/object. Hence, it tests the integration between classes i.e dependencies. It is used to test if the database is returning the correct results, if an external API is returning with proper data and data structure, etc. It tests the real classes and functionalities rather than using mocks. It is significantly slower compared to unit tests, since they interact with databases and external providers.
  4. Acceptance Testing / UI Testing: Acceptance testing is the highest level of testing. It relates more on the front-end UI side. It only cares if the feature works through the vantage point of end-users/customers. The test flow goes through the website clicking and submitting forms and expecting correct results for failed results based on data submitted. We use tools like Selenium for this purpose. It’s automating web applications for testing purposes..

Error related to only_full_group_by when executing a query in MySql

I upgraded my system from MySQL 5.4 to 5.7.17 with PHP for a web application I’m working on. I have a query that is dynamically created, and when run in older versions of MySql it works fine. Since upgrading to 5.7.17 I get this error:

Expression #1 of SELECT list is not in GROUP BY clause and contains nonaggregated column ‘xxx.tablenamehere’ which is not functionally dependent on columns in GROUP BY clause; this is incompatible with sql_mode=only_full_group_by

This is my query:

$sql = <<<SQL
                    SELECT o.appraisal_order_id, o.requestor_id, c.org_name
                        from $dbom.appraisal_orders o 
                            inner join $dbom.requestor c on o.requestor_id = c.requestor_id
                                where o.provider_id =%1% group by c.requestor_id
SQL;
            
            $rtn = $db->GetRows($sql, $UID);
            return $rtn;

So I tried to alter the query a few times, run it again but there was no luck. Then I found a solution and decide to give it a try. Logged in to MySQL server and I ran these 2 statements that I found on stackoverflow forums. And it works.

mysql> set global sql_mode='STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION';
mysql> set session sql_mode='STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION';

or in Mysql/my.ini, you can add this sql_mode line in mysqld section, then restart MySQL server.

[mysqld]
sql_mode=STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION

Adding Comment Search Box to comments section

When the comments section of a post/page is getting traction, users couldn’t be able to go thru each page in the pagination area. It would be nice to add a search box right above the comments section where visitors just type a keyword to search thru all the comments of that particular post/page.


<div class="prw_rup prw_filters_query_resp" data-prwidget-name="filters_query_resp" data-prwidget-init="handlers"><div class="title">Show reviews that mention</div>

<div class="uk-formR">
<form method="get" >
<input type="text" name="cs" >
<input type="submit" name="submit" value="Search">
</form>
</div>

Writing a trigger to generate uuid in a table

If you never had a field containing uuid before in MySQL table, now you can add a new field default is null. Then create a trigger so that every time there’s a new record inserted, the uuid will be automatically generated for that row. Here’s how you write a trigger to add uuid to a field “user_api_key” in the table “api_users”

DELIMITER $$

CREATE
    /*[DEFINER = { user | CURRENT_USER }]*/
    TRIGGER `test`.`add uuid to api_users table` AFTER INSERT
    ON `test`.`api_users`
    FOR EACH ROW BEGIN
	IF new.user_api_key IS NULL THEN
	SET new.user_api_key =UUID();
	END IF;
    END$$

DELIMITER ;

If you run into this error, make sure you don’t duplicate the trigger.

This version of MySQL doesn’t yet support ‘multiple triggers with the same action time and event for one table.

To check for duplicate trigger, use this statement

SHOW TRIGGERS WHERE `table` = 'api_users';

Color Detection Programming

Today we’re going to use NodeJS to write a program that can detect colors from an image. User uploads an image, NodeJS will process the image on the Server side and response with a list of color RGB values. It will return predictions about the dominant colors in an image.

We test with a US flag PNG image using NodeJS

.from('./_lab/img/usflag.png').getPalette((err, palette) => console.log(palette))
.from('./_lab/img/usflag.png').getSwatches((err, swatches) => console.log(swatches))

And the response from server is:

Swatch {
_rgb: [220, 4, 4],
_population: 324,
_hsl: [0, 0.9642857142857144, 0.4392156862745098]
},
LightVibrant:
Swatch {
_rgb: [228, 70, 70],
_population: 360,
_hsl: [0, 0.7452830188679245, 0.5843137254901961]
},
DarkVibrant:
Swatch {
_rgb: [5, 5, 82],
_population: 319,
_hsl: [0.6666666666666666, 0.885057471264368, 0.17058823529411765]
},
Muted:
Swatch {
_rgb: [168, 108, 112],
_population: 0,
_hsl: [0.9888888888888889, 0.2564102564102564, 0.5411764705882353]
},
LightMuted:
Swatch {
_rgb: [181, 181, 193],
_population: 50,
_hsl: [0.6666666666666666, 0.08823529411764695, 0.7333333333333334]
},
DarkMuted:
Swatch {
_rgb: [66, 57, 114],
_population: 56,
_hsl: [0.6929824561403509, 0.3333333333333333, 0.33529411764705885]
}