<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Grace Valerie</title>
    <description>The latest articles on DEV Community by Grace Valerie (@valgrace).</description>
    <link>https://dev.to/valgrace</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F1054814%2F1376a1ff-6479-48ce-902b-faa3f72b2159.jpeg</url>
      <title>DEV Community: Grace Valerie</title>
      <link>https://dev.to/valgrace</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/valgrace"/>
    <language>en</language>
    <item>
      <title>How analysts translate messy data, and Dashboards into actions in Power BI</title>
      <dc:creator>Grace Valerie</dc:creator>
      <pubDate>Mon, 09 Feb 2026 16:22:13 +0000</pubDate>
      <link>https://dev.to/valgrace/how-analysts-translate-messy-data-and-dashboards-into-actions-in-power-bi-3i21</link>
      <guid>https://dev.to/valgrace/how-analysts-translate-messy-data-and-dashboards-into-actions-in-power-bi-3i21</guid>
      <description>&lt;p&gt;The main goal for data analysts is to make sense of data and express findings to respective stakeholders. The analyst imports into Power BI from different sources, upon examining it is not prepared for analysis.&lt;br&gt;
Simple mistakes such as columns with string data types containing numeric rows, columns containing errors and null values, duplicated unique identifiers can make the data unusable.&lt;/p&gt;
&lt;h3&gt;
  
  
  Data Cleaning and Preparation
&lt;/h3&gt;

&lt;p&gt;Power BI offers Power Query which is powerful for preparing and cleaning data. Clean data is beneficial for:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Producing more accurate results when performing calculations&lt;/li&gt;
&lt;li&gt;Finding data more intuitively due to better organization&lt;/li&gt;
&lt;li&gt;Simpler navigation and effective use of slicers.&lt;/li&gt;
&lt;/ul&gt;
&lt;h4&gt;
  
  
  Steps for cleaning data
&lt;/h4&gt;

&lt;ol&gt;
&lt;li&gt;First step is transforming your imported data to ensure it is suitable for use. Open Power Query editor by clicking on transform data in the queries section of the menu.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fvjcwwi7zqq4ei3xje7zp.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fvjcwwi7zqq4ei3xje7zp.png" alt="transform data icon" width="226" height="142"&gt;&lt;/a&gt;&lt;br&gt;
Power Query will only modify a view of your data and not your original data.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Next is to identify column headers and names. In the case of the example below, column names are non-descriptive making it hard to understand what each column represents.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Furwk273vscrls17qtljw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Furwk273vscrls17qtljw.png" alt="non descriptive column names" width="800" height="299"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;When you go to transform data, the correct column names are displayed as the first row. Select the table home icon as shown and on the dropdown, click on Use first Rows as header.&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffzj2h981kw5chy3h5ei8.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffzj2h981kw5chy3h5ei8.png" alt="table home icon " width="800" height="98"&gt;&lt;/a&gt;&lt;br&gt;
Its also possible to change the header from the menu.&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fnffo466e3cfz1a1hd8bc.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fnffo466e3cfz1a1hd8bc.png" alt="Transform section on the menu" width="451" height="152"&gt;&lt;/a&gt;&lt;br&gt;
Now the correct headers will be displayed&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F871vzitg79ar6funh0r4.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F871vzitg79ar6funh0r4.png" alt="correct headers" width="800" height="42"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Verify that the column names are correct by removing spelling errors, and ensuring the naming convention is user friendly. In this case column names are capitalized, if using snake case or any other convention, ensure all columns are consistent.&lt;br&gt;
To rename a column, right click the column name and select rename. In this case we can rename the Location column to Order Location.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fmv8hh9fcwbb4nvcv43pr.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fmv8hh9fcwbb4nvcv43pr.png" alt="location change" width="246" height="330"&gt;&lt;/a&gt;&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F91ss23tm3uqbvohpcdlx.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F91ss23tm3uqbvohpcdlx.png" alt="order location" width="240" height="185"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You can also remove any column you find unnecessary by going to&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fc83whjmb923z4z6rzm4k.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fc83whjmb923z4z6rzm4k.png" alt="remove columns menu" width="638" height="147"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Every time you make a change when transforming data, it will be displayed on the properties tab.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fbovimoz3xwflna3o7kqu.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fbovimoz3xwflna3o7kqu.png" alt="applied steps tab" width="306" height="549"&gt;&lt;/a&gt;&lt;br&gt;
You can easily undo a change by clicking on the X.&lt;/p&gt;
&lt;h5&gt;
  
  
  Duplicates
&lt;/h5&gt;

&lt;p&gt;Remove duplicates from columns to only keep unique names for selected columns. We have identified that each transaction should be unique and no two transactions can share a transaction id. In this example, we remove duplicate transactions by right clicking transaction id and selecting remove duplicates.&lt;/p&gt;
&lt;h5&gt;
  
  
  Incorrect data types
&lt;/h5&gt;

&lt;p&gt;When importing data, some column data types are incorrectly interpreted such as numeric data saved as text. In this case, data formatted on the left implies it is text while numeric data will be formatted on the right.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F583n1odqz2hf3v5bqka0.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F583n1odqz2hf3v5bqka0.png" alt="incorrect data types" width="728" height="346"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;When you click a specific column name the data type will also be displayed in the menu as follows&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fykkv6y388vra8mjiaysi.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fykkv6y388vra8mjiaysi.png" alt="text data type" width="800" height="289"&gt;&lt;/a&gt;&lt;br&gt;
Click on the dropdown to select the appropriate data type.&lt;br&gt;
Incorrect data types can prevent you from creating hierarchies, performing calculations, or forming proper relationships with other entities.&lt;/p&gt;

&lt;p&gt;In this example we transformed the following columns data types into whole numbers, decimal and date types&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7kdpq6a8negf9hzkbwk1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7kdpq6a8negf9hzkbwk1.png" alt="transform data types" width="800" height="131"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h5&gt;
  
  
  Replacing nulls, Errors and blanks
&lt;/h5&gt;

&lt;p&gt;These types prevent you from performing calculations and summarization on data. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F8v02ouhuu31jqgkvy3xx.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F8v02ouhuu31jqgkvy3xx.png" alt="replace values bi" width="292" height="164"&gt;&lt;/a&gt;&lt;br&gt;
Power query uses find and replace to find the values in a row you want to replace and change to the specified value.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6mxbk0kgurezt5vovqk1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6mxbk0kgurezt5vovqk1.png" alt="find and replace" width="642" height="277"&gt;&lt;/a&gt;&lt;br&gt;
Replace errors and blanks with unknown.&lt;/p&gt;

&lt;p&gt;Use column distribution in the view tab to detect anomalies in your data.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fb93qggtyazwsgavww584.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fb93qggtyazwsgavww584.png" alt="detect anomaly" width="800" height="428"&gt;&lt;/a&gt;&lt;br&gt;
Once you are done with cleaning and preparing your data in power query, you can click on close and apply.&lt;/p&gt;
&lt;h4&gt;
  
  
  Data Analysis Expressions
&lt;/h4&gt;

&lt;p&gt;These are functions and operators that can be combined to build formulas in Power BI&lt;/p&gt;
&lt;h5&gt;
  
  
  Common DAX Functions
&lt;/h5&gt;
&lt;h6&gt;
  
  
  Aggregation Functions
&lt;/h6&gt;

&lt;p&gt;&lt;code&gt;SUM&lt;/code&gt; - adds all the numeric values in a given column and returns a decimal number.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;= SUM(column)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We can find the total revenue by summing all orders&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fa9pn8bz9vyhaqckaekjn.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fa9pn8bz9vyhaqckaekjn.png" alt="revenue" width="507" height="42"&gt;&lt;/a&gt;&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6szt3ijmh8tx8v8euaat.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6szt3ijmh8tx8v8euaat.png" alt="revenue measure" width="382" height="231"&gt;&lt;/a&gt;&lt;br&gt;
&lt;code&gt;AVERAGE&lt;/code&gt; - Returns the average mean of all numeric values in a column. Null values may cause the average to result in an error.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;AVERAGE(column)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In an example you can calculate the average of customers loyalty score as shown &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4j61tw8039l0egw0rz6p.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4j61tw8039l0egw0rz6p.png" alt="average loyalty score" width="716" height="67"&gt;&lt;/a&gt;&lt;br&gt;
The above is achieved by creating a new measure which is a dynamic calculation on data that is created using DAX.&lt;br&gt;
We can view the result of the measure using a card in report view.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fzowizmvza0hekjicaf02.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fzowizmvza0hekjicaf02.png" alt="loyalty score card" width="516" height="402"&gt;&lt;/a&gt;&lt;br&gt;
&lt;code&gt;COUNT&lt;/code&gt; - Used to count the number of rows in the specified column which and NON-BLANK&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fjgh6w23qtq54srmaj8mi.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fjgh6w23qtq54srmaj8mi.png" alt="total products" width="572" height="46"&gt;&lt;/a&gt;&lt;br&gt;
&lt;code&gt;COUNTROWS&lt;/code&gt; - This is used when you want to count the number of rows in the specified table defined by an expression&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Total Electronic Products =
CALCULATE(
    COUNTROWS(Products),
    Products[Category] = "Electronics"
)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The above &lt;code&gt;COUNTROWS&lt;/code&gt; example returns the count of only products in the electronics category&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fza7jyyj23qgv68h67wu4.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fza7jyyj23qgv68h67wu4.png" alt="count rows" width="383" height="140"&gt;&lt;/a&gt;&lt;br&gt;
&lt;code&gt;SUMX&lt;/code&gt; - evaluates the expression for each row in a table then returns the sum. It is referred to as an iterator function and only counts numeric rows.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;SUMX(
    Table,
    Expression
)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h6&gt;
  
  
  Filter Functions
&lt;/h6&gt;

&lt;p&gt;Powerful functions that let you manipulate data context&lt;br&gt;
&lt;code&gt;CALCULATE&lt;/code&gt; - used to evaluate an expression&lt;br&gt;
&lt;code&gt;FILTER&lt;/code&gt; - returns a subset of a different table as a new table&lt;br&gt;
&lt;code&gt;INDEX&lt;/code&gt; - &lt;br&gt;
&lt;code&gt;RANGE&lt;/code&gt;&lt;br&gt;
&lt;code&gt;RANK&lt;/code&gt;&lt;/p&gt;
&lt;h6&gt;
  
  
  Date and Time Functions
&lt;/h6&gt;

&lt;p&gt;&lt;code&gt;CALENDAR&lt;/code&gt; - returns a new table with a single column of a set of dates.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;= CALENDAR (DATE (2024, 7, 1), DATE (2026, 7, 31)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F58yncv8wmfertxf6ix6l.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F58yncv8wmfertxf6ix6l.png" alt="calendar dates" width="800" height="42"&gt;&lt;/a&gt;&lt;br&gt;
&lt;code&gt;DATE&lt;/code&gt; - returns the date in datetime format.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;DATE(yyyy, mmm, dd)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;DATEVALUE&lt;/code&gt; - converts text value to date in datetime format. &lt;/p&gt;

&lt;h4&gt;
  
  
  Dashboards in Power BI
&lt;/h4&gt;

&lt;p&gt;Dashboards are used in power bi to tell a story about the data through visualizations. It highlights the important details that can be reviewed in the report&lt;br&gt;
Here is a simple example of a dashboard&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F3uzhkq1q68xy7032pxxh.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F3uzhkq1q68xy7032pxxh.png" alt="dashboard visual" width="800" height="463"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Conclusion
&lt;/h3&gt;

&lt;p&gt;To get the most out of data we need to transform it, perform calculations and create intuitive dashboards that summarize all the insights from the data. Power BI is a powerful tool to achieving this. Understanding and following the right steps will help data analysts to analyze data efficiently.&lt;/p&gt;

</description>
      <category>powerbi</category>
      <category>dax</category>
      <category>dashboards</category>
      <category>powerquery</category>
    </item>
    <item>
      <title>Data Modelling in Power BI</title>
      <dc:creator>Grace Valerie</dc:creator>
      <pubDate>Mon, 02 Feb 2026 06:53:36 +0000</pubDate>
      <link>https://dev.to/valgrace/data-modelling-in-power-bi-4jn8</link>
      <guid>https://dev.to/valgrace/data-modelling-in-power-bi-4jn8</guid>
      <description>&lt;p&gt;Data modelling helps to define the relationship between sources of data. Organizations work with large amounts of data which require modelling, before building reports. This article is a practical guide for building performance optimized data models in Power BI.&lt;/p&gt;

&lt;p&gt;Data models in Power BI are referred to as semantic models. The data model is where you describe and organize your data.&lt;/p&gt;

&lt;p&gt;** How to build relationships&lt;/p&gt;

&lt;h4&gt;
  
  
  Modelling Approaches
&lt;/h4&gt;

&lt;p&gt;There is a sequence of steps followed when creating a data model. These include:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Identifying all the object entities and attributes in your data model.&lt;/li&gt;
&lt;li&gt;Identifying the relationships between entities in your data model.&lt;/li&gt;
&lt;li&gt;Deriving the best modelling approach from the entities and relationships.&lt;/li&gt;
&lt;li&gt;Optimizing your model for performance&lt;/li&gt;
&lt;/ol&gt;

&lt;h4&gt;
  
  
  Star Schema
&lt;/h4&gt;

&lt;p&gt;This type of modelling approach is widely adopted for relational data. It consists of one central table known as a fact table connected to another table or tables known as dimension tables. The star schema ensures data is denormalized to improve performance by reducing the number of joins needed to retrieve data. Fact tables mainly contain quantitative data while dimension tables describe entities.&lt;/p&gt;

&lt;h5&gt;
  
  
  Types of Relationships
&lt;/h5&gt;

&lt;p&gt;Every relationship is represented by its cardinality type:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;One-to-one&lt;/li&gt;
&lt;li&gt;One-to-many&lt;/li&gt;
&lt;li&gt;Many-to-one&lt;/li&gt;
&lt;li&gt;Many-to-many&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The star schema is best represented by the one-to-many cardinality because the fact table connects to multiple dimension tables.&lt;/p&gt;

&lt;h5&gt;
  
  
  Data Denormalization
&lt;/h5&gt;

&lt;p&gt;This technique is used to improve query performance in star schemas. All redundant data are added to the fact table to maintain one single source of truth.&lt;/p&gt;

&lt;h5&gt;
  
  
  Snowflake Schema
&lt;/h5&gt;

&lt;p&gt;In this type of schema data is normalized into multiple related sub-dimension tables. This avoids data duplication and is more suitable for complex data. This schema is more suitable for hierarchical data and data that changes often. Snowflake schemas also save storage space since data is normalized.&lt;/p&gt;

&lt;h3&gt;
  
  
  Conclusion
&lt;/h3&gt;

&lt;p&gt;Star schemas are preferred when building data warehouses since they are optimized for better performance by reducing the number of queries and need for joins. For &lt;/p&gt;

</description>
      <category>dataengineering</category>
      <category>schema</category>
      <category>powerbi</category>
      <category>datamodelling</category>
    </item>
    <item>
      <title>Useful Linux Commands For Data Engineers</title>
      <dc:creator>Grace Valerie</dc:creator>
      <pubDate>Mon, 26 Jan 2026 00:58:05 +0000</pubDate>
      <link>https://dev.to/valgrace/useful-linux-commands-for-data-engineers-3082</link>
      <guid>https://dev.to/valgrace/useful-linux-commands-for-data-engineers-3082</guid>
      <description>&lt;p&gt;Linux servers dominate as the most preferred compute environment for large scale data systems. Mastering Linux helps data engineers to efficiently manage data pipelines and process data.&lt;/p&gt;

&lt;p&gt;This article is a deep dive into the most useful Linux commands that are relevant for data engineering tasks.&lt;/p&gt;

&lt;h3&gt;
  
  
  Prerequisites
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;Setup a Linux server environment for testing purposes.&lt;/li&gt;
&lt;li&gt;Should be familiar with the command line&lt;/li&gt;
&lt;/ol&gt;




&lt;h2&gt;
  
  
  Table of Contents
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;File and Directory Operations&lt;/li&gt;
&lt;li&gt;File System and Storage Management&lt;/li&gt;
&lt;li&gt;File Attributes and Permissions&lt;/li&gt;
&lt;li&gt;User and Group Management&lt;/li&gt;
&lt;li&gt;Networking and Security&lt;/li&gt;
&lt;li&gt;File Compression and Encryption&lt;/li&gt;
&lt;li&gt;Editors&lt;/li&gt;
&lt;li&gt;File transfer commands&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  File and Directory Operations
&lt;/h3&gt;

&lt;p&gt;These commands are used for navigating and manipulating the Linux file system. They emulate CRUD operations, but on the file structure.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# returns the current working directory
&lt;/span&gt;&lt;span class="n"&gt;pwd&lt;/span&gt;

&lt;span class="c1"&gt;# lists directory contents including files and subdirectories
&lt;/span&gt;&lt;span class="n"&gt;ls&lt;/span&gt; 
&lt;span class="c1"&gt;# includes hidden files in the list
&lt;/span&gt;&lt;span class="n"&gt;ls&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;
&lt;span class="c1"&gt;# changes the current working directory // cd /path/to/directory
&lt;/span&gt;&lt;span class="n"&gt;cd&lt;/span&gt; 
&lt;span class="c1"&gt;# deleting files and directories 
&lt;/span&gt;&lt;span class="n"&gt;rm&lt;/span&gt;
&lt;span class="c1"&gt;# creating a file
&lt;/span&gt;&lt;span class="n"&gt;touch&lt;/span&gt;
&lt;span class="c1"&gt;# returns the contents of a file 
&lt;/span&gt;&lt;span class="n"&gt;cat&lt;/span&gt; 
&lt;span class="c1"&gt;# quickly view the first or last lines of a file without opening the entire file.
&lt;/span&gt;&lt;span class="n"&gt;head&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="n"&gt;tail&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Data engineers can use these commands to inspect logs and raw data dumps.&lt;/p&gt;

&lt;h3&gt;
  
  
  File System and Storage Management
&lt;/h3&gt;

&lt;p&gt;The file system partitions, organizes and stores data on disk.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight cpp"&gt;&lt;code&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;dev&lt;/span&gt; &lt;span class="o"&gt;~&lt;/span&gt; &lt;span class="n"&gt;directory&lt;/span&gt; &lt;span class="n"&gt;representing&lt;/span&gt; &lt;span class="n"&gt;actual&lt;/span&gt; &lt;span class="n"&gt;storage&lt;/span&gt; &lt;span class="n"&gt;disks&lt;/span&gt;
&lt;span class="n"&gt;sd&lt;/span&gt; &lt;span class="o"&gt;~&lt;/span&gt; &lt;span class="n"&gt;the&lt;/span&gt; &lt;span class="n"&gt;storage&lt;/span&gt; &lt;span class="n"&gt;disk&lt;/span&gt;
&lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="o"&gt;~&lt;/span&gt; &lt;span class="n"&gt;the&lt;/span&gt; &lt;span class="n"&gt;first&lt;/span&gt; &lt;span class="n"&gt;disk&lt;/span&gt; 
&lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="o"&gt;~&lt;/span&gt; &lt;span class="n"&gt;first&lt;/span&gt; &lt;span class="n"&gt;partition&lt;/span&gt; &lt;span class="n"&gt;on&lt;/span&gt; &lt;span class="n"&gt;the&lt;/span&gt; &lt;span class="n"&gt;disk&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;cat /proc/partitions&lt;/code&gt; ~ view all storage disks and partitions recognized by the system&lt;br&gt;
&lt;code&gt;fdisk /dev/sda&lt;/code&gt; ~ create, manage and delete partitions on &lt;code&gt;/dev/sda&lt;/code&gt;&lt;br&gt;
&lt;code&gt;sudo mkfs.xfs /dev/sdb1&lt;/code&gt; ~ install a filesystem on partition &lt;code&gt;/dev/sdb1&lt;/code&gt;&lt;br&gt;
&lt;code&gt;sudo mount /dev/sdb1 /myfolder&lt;/code&gt; ~ attach storage space to myfolder directory which acts as the mount point&lt;br&gt;
 &lt;code&gt;df -f /myfolder&lt;/code&gt; ~ verify the storage space exists&lt;br&gt;
&lt;code&gt;pvcreate /dev/sdb1&lt;/code&gt; ~ initialize a physical volume to use with the Logical Volume Manager&lt;/p&gt;

&lt;p&gt;As data engineers work on systems with intensive data, they need to skillfully manipulate partitions and filesystems to prevent losing data. Backing up data is recommended before running these commands.&lt;/p&gt;
&lt;h3&gt;
  
  
  File Attributes and Permissions
&lt;/h3&gt;

&lt;p&gt;Linux file permissions offer a security mechanism for determining who can read, write or execute files on a system.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight cpp"&gt;&lt;code&gt;&lt;span class="cp"&gt;# returns file metadata including file permissions
&lt;/span&gt;&lt;span class="n"&gt;ls&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;l&lt;/span&gt; 

&lt;span class="cp"&gt;# makes a file immutable
&lt;/span&gt;&lt;span class="n"&gt;chattr&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt; 

&lt;span class="cp"&gt;# list file attributes
&lt;/span&gt;&lt;span class="n"&gt;lsattr&lt;/span&gt; 

&lt;span class="cp"&gt;# add or remove execute permissions
&lt;/span&gt;&lt;span class="n"&gt;chmod&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="n"&gt;or&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt; 

&lt;span class="cp"&gt;# set Read/Write for owner, read for group/others
&lt;/span&gt;&lt;span class="n"&gt;chmod&lt;/span&gt; &lt;span class="mi"&gt;644&lt;/span&gt; &lt;span class="n"&gt;myapp&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;py&lt;/span&gt;
&lt;span class="cp"&gt;# change file ownership
&lt;/span&gt; &lt;span class="n"&gt;chown&lt;/span&gt; 

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Using these commands, a data engineer will be able restrict access to sensitive file data and protect files from accidental modifications by setting strict permissions.&lt;/p&gt;

&lt;h3&gt;
  
  
  User and Group Management
&lt;/h3&gt;

&lt;p&gt;Use the &lt;code&gt;useradd&lt;/code&gt; command to create a new user&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;sudo&lt;/span&gt; &lt;span class="n"&gt;useradd&lt;/span&gt; &lt;span class="n"&gt;username&lt;/span&gt;

&lt;span class="c1"&gt;#create new group
&lt;/span&gt;&lt;span class="n"&gt;sudo&lt;/span&gt; &lt;span class="n"&gt;groupadd&lt;/span&gt; &lt;span class="n"&gt;groupname&lt;/span&gt;

&lt;span class="c1"&gt;# -m ~creates the home directory for the user
&lt;/span&gt;&lt;span class="n"&gt;sudo&lt;/span&gt; &lt;span class="n"&gt;useradd&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;m&lt;/span&gt; &lt;span class="n"&gt;username&lt;/span&gt;

&lt;span class="c1"&gt;# assign the user to a specific group
&lt;/span&gt;&lt;span class="n"&gt;sudo&lt;/span&gt; &lt;span class="n"&gt;useradd&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;G&lt;/span&gt; &lt;span class="n"&gt;groupname&lt;/span&gt; &lt;span class="err"&gt;$&lt;/span&gt;&lt;span class="n"&gt;username&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;View user information with&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="nb"&gt;id&lt;/span&gt; &lt;span class="n"&gt;username&lt;/span&gt;
&lt;span class="c1"&gt;# returns UID and GID
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To add a password for the new user, run:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;passwd username
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;All existing users will be listed in the &lt;code&gt;/etc/passwd&lt;/code&gt; file&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;cat /etc/passwd
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Switch to a different user with&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;su &lt;span class="nt"&gt;-h&lt;/span&gt; username

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In order for data engineers to maintain least privilege access to resources, they need to properly implement user and group management. It is recommended to use user accounts instead of the root user to minimize access.&lt;/p&gt;

&lt;h3&gt;
  
  
  Networking and Security
&lt;/h3&gt;

&lt;p&gt;At the center of Linux are four key components that block malicious access - Firewalls filter traffic, Encryption encrypts data in transit, Authentication verifies user identities, Monitoring analyzes traffic.&lt;/p&gt;

&lt;p&gt;Using UFW which is a firewall interface for iptables, you can check the currently registered profiles with&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;ufw app list
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To enable an application profile, RUN&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;ufw allow appname
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;There is a rule that allows you to specify the port instead of the profile name&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# check if ufw is running
&lt;/span&gt;&lt;span class="n"&gt;sudo&lt;/span&gt; &lt;span class="n"&gt;ufw&lt;/span&gt; &lt;span class="n"&gt;status&lt;/span&gt;

&lt;span class="c1"&gt;# allow ssh
&lt;/span&gt;&lt;span class="n"&gt;sudo&lt;/span&gt; &lt;span class="n"&gt;ufw&lt;/span&gt; &lt;span class="n"&gt;allow&lt;/span&gt; &lt;span class="mi"&gt;22&lt;/span&gt;

&lt;span class="c1"&gt;# specify port ranges (apply with specific protocol)
&lt;/span&gt;&lt;span class="n"&gt;sudo&lt;/span&gt; &lt;span class="n"&gt;ufw&lt;/span&gt; &lt;span class="n"&gt;allow&lt;/span&gt; &lt;span class="mi"&gt;6000&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;6009&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;tcp&lt;/span&gt;

&lt;span class="c1"&gt;# allow connections from IP address
&lt;/span&gt;&lt;span class="n"&gt;sudo&lt;/span&gt; &lt;span class="n"&gt;ufw&lt;/span&gt; &lt;span class="n"&gt;allow&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="mf"&gt;201.8&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mf"&gt;139.4&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;With the rules applied you can enable firewall with:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;ufw &lt;span class="nb"&gt;enable&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;use &lt;code&gt;sudo ss --tulnp|grep&lt;/code&gt; to show listening ports and &lt;code&gt;ping&lt;/code&gt; to test connectivity.&lt;/p&gt;

&lt;h3&gt;
  
  
  File Compression and Encryption
&lt;/h3&gt;

&lt;p&gt;Compressing a file reduces the amount of storage needed and will help speed up data transfer.&lt;/p&gt;

&lt;p&gt;Use &lt;code&gt;gzip&lt;/code&gt; to compress a single file as:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# results in filename.gz
&lt;/span&gt;&lt;span class="n"&gt;gzip&lt;/span&gt; &lt;span class="n"&gt;filename&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The process of archiving will combine multiple files into a single file archive. create a simple archive using &lt;code&gt;tar&lt;/code&gt; package&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# -cf creates and names the archive
&lt;/span&gt;&lt;span class="n"&gt;tar&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;cf&lt;/span&gt; &lt;span class="n"&gt;myarchive&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;tar&lt;/span&gt; &lt;span class="n"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;py&lt;/span&gt; &lt;span class="n"&gt;main&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;py&lt;/span&gt; &lt;span class="n"&gt;project&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To extract an archive use the command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;tar&lt;/span&gt; &lt;span class="nt"&gt;-xf&lt;/span&gt; myarchive.tar
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Encryption will ensure that you can safely transit the data over the internet. Use GPG or openssl for encryption&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# File encrypted using passphrase
&lt;/span&gt;&lt;span class="n"&gt;gpg&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;c&lt;/span&gt; &lt;span class="n"&gt;filename&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;txt&lt;/span&gt;

&lt;span class="c1"&gt;# AES encryption
&lt;/span&gt;&lt;span class="n"&gt;openssl&lt;/span&gt; &lt;span class="n"&gt;enc&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;aes&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;256&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;cbc&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;txt&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;out&lt;/span&gt; &lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;enc&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Data engineers can compress raw log files to save space, then encrypt data archived files before uploading to cloud storage.&lt;/p&gt;

&lt;h3&gt;
  
  
  Editors
&lt;/h3&gt;

&lt;p&gt;The most popular text editors on Linux are Nano and Vim.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;nano file.txt

vi file.txt
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Both commands will create if not exists, then open file.txt &lt;/p&gt;

&lt;h3&gt;
  
  
  File transfer commands
&lt;/h3&gt;

&lt;p&gt;These commands can be used to handle file transfer either locally or remotely.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# Secure File Transfer Protocol ~ used for transferring files
&lt;/span&gt;&lt;span class="n"&gt;sftp&lt;/span&gt; &lt;span class="n"&gt;username&lt;/span&gt;&lt;span class="nd"&gt;@ip_address&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;hostname&lt;/span&gt;

&lt;span class="c1"&gt;# copy files and directories locally
&lt;/span&gt;&lt;span class="n"&gt;cp&lt;/span&gt; &lt;span class="n"&gt;file1&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;txt&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;backup&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;file1&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;txt&lt;/span&gt;

&lt;span class="c1"&gt;# move or rename files
&lt;/span&gt;&lt;span class="n"&gt;mv&lt;/span&gt; &lt;span class="n"&gt;filename&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="n"&gt;renamedfile&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;

&lt;span class="c1"&gt;# transfer files remotely over ssh
&lt;/span&gt;&lt;span class="n"&gt;scp&lt;/span&gt; &lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;csv&lt;/span&gt; &lt;span class="n"&gt;username&lt;/span&gt;&lt;span class="nd"&gt;@ip_address&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;

&lt;span class="c1"&gt;#synchronize directories remotely for incremental updates
&lt;/span&gt;&lt;span class="n"&gt;rsync&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;avz&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;backup&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;log&lt;/span&gt; &lt;span class="n"&gt;username&lt;/span&gt;&lt;span class="nd"&gt;@ip_address&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;hostname&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A data engineer will be able to efficiently sync files on the local server to a remote server.&lt;/p&gt;

&lt;h3&gt;
  
  
  Conclusion
&lt;/h3&gt;

&lt;p&gt;This article covers several categories of Linux commands and how data engineers use them.&lt;/p&gt;

&lt;h3&gt;
  
  
  References
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://thenewstack.io/how-to-manage-linux-storage/" rel="noopener noreferrer"&gt;How to Manage Linux Storage&lt;/a&gt;&lt;br&gt;
&lt;a href="https://www.redhat.com/en/blog/linux-file-permissions-explained" rel="noopener noreferrer"&gt;Linux file permissions explained&lt;/a&gt;&lt;br&gt;
&lt;a href="https://linuxvox.com/blog/difference-between-archiving-and-compression/" rel="noopener noreferrer"&gt;Differences between archiving and compression&lt;/a&gt;&lt;/p&gt;

</description>
      <category>dataengineering</category>
      <category>linux</category>
      <category>vim</category>
      <category>ssh</category>
    </item>
    <item>
      <title>Basics of using Git</title>
      <dc:creator>Grace Valerie</dc:creator>
      <pubDate>Sun, 18 Jan 2026 09:16:55 +0000</pubDate>
      <link>https://dev.to/valgrace/basics-of-using-git-171a</link>
      <guid>https://dev.to/valgrace/basics-of-using-git-171a</guid>
      <description>&lt;p&gt;In this article, we'll cover the basics of using git, how version control systems work, and how to push and pull code. &lt;/p&gt;

&lt;h2&gt;
  
  
  What is version control?
&lt;/h2&gt;

&lt;p&gt;Version control is a system that keeps track of changes made to your codebase over time. It is like keeping a digital copy of your files somewhere on the internet where other people can make changes to those files. It allows developers to collaborate effectively, with the freedom of knowing every change to the repository can be easily reverted. &lt;/p&gt;

&lt;h3&gt;
  
  
  Why use version control?
&lt;/h3&gt;

&lt;p&gt;Version control comes with a lot of benefits that make it easier for projects to exist long term:- &lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;A history of all changes made to a codebase are maintained making it easy to manage different versions of the same software.&lt;/li&gt;
&lt;li&gt;It can easily identify incompatible changes made to a codebase and help you rectify before causing any permanent damage.&lt;/li&gt;
&lt;li&gt;It helps distributed teams to coordinate their work in fast paced software delivery workflows.&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Types of Version Control Systems
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Centralized Version Control&lt;/strong&gt;&lt;br&gt;
There is one centralized repository which hosts different versions of the code. Every User commits directly to the main branch. A developer can lock a file that contains a piece of code they are working on to avoid conflict with other developers. This system is more suitable for small teams working with huge binary files. Instead of downloading the entire codebase, they can just download a subset of what they need. The downside to this system is it creates a single point of failure such that, when the repository server is down no one can access their codebase. Examples of centralized version control tools include &lt;em&gt;perforce&lt;/em&gt; and &lt;em&gt;subversion&lt;/em&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Localized Version Control&lt;/strong&gt;&lt;br&gt;
This system operates entirely on one server and does not require any remote connection. This is more ideal for personal projects or single user contributions. A structured revision of history is still maintained to enable rollbacks after accidental file modifications that are causing errors. The most widely used local version control tool is known as revision version control. It stores the differences between file versions known as patch sets and allows you to recreate any file versions by applying patches.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Distributed version control&lt;/strong&gt;&lt;br&gt;
Every contributor download a local copy of the repository which fully mirrors everything in the central repository. This allows developers to work offline and later synchronize changes. This system helps development teams to set up strong workflows. developers can easily sync their code and maintainers can set up code review processes to maintain code quality. Examples of tools include Mercurial, Bazaar and Git.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  The Journey From Git Init
&lt;/h3&gt;

&lt;p&gt;This section covers the basics of using git to work with a repository. It covers: &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt; How to create a repository&lt;/li&gt;
&lt;li&gt; How to push code to a repository&lt;/li&gt;
&lt;li&gt; How to pull a repository version&lt;/li&gt;
&lt;li&gt; How to track changes made to a repository
We will work solely with the command line to achieve this.&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  Prerequisites
&lt;/h4&gt;

&lt;ol&gt;
&lt;li&gt;Have git bash installed&lt;/li&gt;
&lt;li&gt;Setup ssh key for GitHub&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Follow these next steps to successfully track your project with git&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Initialize your repository
The first step is to navigate to the project directory you are working on as
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="n"&gt;cd&lt;/span&gt; &lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;to&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;project&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;myproject&lt;/span&gt; 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In the root directory of this project is where you want to initialize git.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git init
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This command creates a new subdirectory &lt;code&gt;.git&lt;/code&gt; which contains all repository files.&lt;/p&gt;

&lt;p&gt;To start tracking your files with git use the &lt;code&gt;git add&lt;/code&gt; command. This command tells git which specific files you want to track&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="n"&gt;git&lt;/span&gt; &lt;span class="k"&gt;add&lt;/span&gt; &lt;span class="p"&gt;.&lt;/span&gt; &lt;span class="o"&gt;//&lt;/span&gt; &lt;span class="n"&gt;track&lt;/span&gt; &lt;span class="k"&gt;all&lt;/span&gt; &lt;span class="n"&gt;files&lt;/span&gt;
&lt;span class="n"&gt;git&lt;/span&gt; &lt;span class="k"&gt;add&lt;/span&gt; &lt;span class="n"&gt;filename&lt;/span&gt; &lt;span class="o"&gt;//&lt;/span&gt;&lt;span class="n"&gt;track&lt;/span&gt; &lt;span class="k"&gt;only&lt;/span&gt; &lt;span class="n"&gt;specified&lt;/span&gt; &lt;span class="n"&gt;filename&lt;/span&gt;
&lt;span class="n"&gt;git&lt;/span&gt; &lt;span class="k"&gt;add&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;py&lt;/span&gt; &lt;span class="o"&gt;//&lt;/span&gt; &lt;span class="n"&gt;track&lt;/span&gt; &lt;span class="k"&gt;all&lt;/span&gt; &lt;span class="n"&gt;files&lt;/span&gt; &lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="n"&gt;the&lt;/span&gt; &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;py&lt;/span&gt; &lt;span class="n"&gt;extension&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;g&lt;/span&gt; &lt;span class="n"&gt;file1&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;py&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;file2&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;py&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Run &lt;code&gt;git status&lt;/code&gt; to see which specific files are being tracked.&lt;/p&gt;

&lt;h3&gt;
  
  
  # Crafting a commit message
&lt;/h3&gt;

&lt;p&gt;The next step is to run &lt;code&gt;git commit&lt;/code&gt; which takes a snapshot of the current file version that you are tracking. The default &lt;code&gt;git commit&lt;/code&gt; message will contain the latest output of &lt;code&gt;git status&lt;/code&gt;.&lt;br&gt;
To override the message with a custom one send&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;git&lt;/span&gt; &lt;span class="n"&gt;commit&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;m&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;This is my first commit&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;. A good commit message is useful for future reference and for other developers using the project. There are a few commit message conventions to follow for uniformity and readability. These include capitalizing the first letter of the message and using flags such as fix, refactor, style to categorize a commit.&lt;br&gt;
The message also needs to be descriptive of the changes you made. Read more about this on &lt;a href="https://www.freecodecamp.org/news/how-to-write-better-git-commit-messages/" rel="noopener noreferrer"&gt;freecodecamp article&lt;/a&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;git&lt;/span&gt; &lt;span class="n"&gt;commit&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;m&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;docs: Added instructions on how to...&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Run &lt;code&gt;git log&lt;/code&gt; to view commit history&lt;/p&gt;

&lt;h4&gt;
  
  
  Working with remote repositories
&lt;/h4&gt;

&lt;p&gt;You need remote repositories to push and pull data from them when sharing your work. Its possible to add remote repositories, remove invalid ones. To add a remote repository run the command&lt;br&gt;
&lt;code&gt;git remote add &amp;lt;shortname&amp;gt; url&lt;/code&gt;. For example on github we can add a remote repo as &lt;code&gt;git remote add firstproject https://github.com/username/firstproject&lt;/code&gt;. You can add multiple remote repositories to your project just by changing the shortname and url.&lt;/p&gt;
&lt;h4&gt;
  
  
  Git Branching
&lt;/h4&gt;

&lt;p&gt;Branches in git emulate a movable pointer that points to a particular commit. Every commit in a particular branch pushes that branch closer to the HEAD. HEAD in git is a symbolic reference that points to the most recent commit in the currently checked-out. branch. This way developers can view which branch has the latest changes and which ones are still behind. &lt;br&gt;
Branching helps developers to test their code in staging branches to verify that the code is Ok before pushing to production.&lt;br&gt;
The default branch is known as master which can be overwritten with the command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;git branch -M main
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Its possible to create a new branch with&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="n"&gt;git&lt;/span&gt; &lt;span class="n"&gt;branch&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;branchname&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;//&lt;/span&gt;&lt;span class="k"&gt;create&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="n"&gt;branch&lt;/span&gt;
&lt;span class="n"&gt;git&lt;/span&gt; &lt;span class="n"&gt;checkout&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;branchname&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;//&lt;/span&gt;&lt;span class="n"&gt;switch&lt;/span&gt; &lt;span class="k"&gt;to&lt;/span&gt; &lt;span class="n"&gt;branch&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Pushing your changes
&lt;/h4&gt;

&lt;p&gt;This is the step where we push our code to the remote repository.  There are different servers where you can push your code such as GitHub, GitLab and BitBucket. &lt;/p&gt;

&lt;p&gt;To push your codebase to a remote repository:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;git&lt;/span&gt; &lt;span class="n"&gt;push&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;remote_name&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;branch&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="c1"&gt;# An example could be 
&lt;/span&gt;&lt;span class="n"&gt;git&lt;/span&gt; &lt;span class="n"&gt;push&lt;/span&gt; &lt;span class="n"&gt;origin&lt;/span&gt; &lt;span class="n"&gt;main&lt;/span&gt;
&lt;span class="c1"&gt;# or
&lt;/span&gt;&lt;span class="n"&gt;git&lt;/span&gt; &lt;span class="n"&gt;push&lt;/span&gt; &lt;span class="n"&gt;backup&lt;/span&gt; &lt;span class="n"&gt;master&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This makes it possible to push to different origins and different branches. You can also merge branches using &lt;code&gt;git merge&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;You can also create a new branch and push to its remote using one command:&lt;br&gt;
&lt;code&gt;git push -u &amp;lt;remote_name&amp;gt; &amp;lt;new_branch&amp;gt;&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;You can push a single specific tag which will create a snapshot of a particular release point version that you may want to deploy&lt;/p&gt;

&lt;p&gt;Before pushing we need to create the tag as:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;git&lt;/span&gt; &lt;span class="n"&gt;tag&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="n"&gt;v1&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;m&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;First release version v1.0&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then push with&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# push only v1.0 tag
&lt;/span&gt;&lt;span class="n"&gt;git&lt;/span&gt; &lt;span class="n"&gt;push&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;remote_name&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;v1&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt; 

&lt;span class="c1"&gt;# push all existing tags
&lt;/span&gt;&lt;span class="n"&gt;git&lt;/span&gt; &lt;span class="n"&gt;push&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;remote_name&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="n"&gt;tags&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Pulling The Latest Version
&lt;/h4&gt;

&lt;p&gt;&lt;code&gt;git pull&lt;/code&gt; is the command used to fetch from remote branches and integrate with your local environment&lt;/p&gt;

&lt;h3&gt;
  
  
  Summary Of Commands Used
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# initialize repository
&lt;/span&gt;&lt;span class="n"&gt;git&lt;/span&gt; &lt;span class="n"&gt;init&lt;/span&gt; 
&lt;span class="c1"&gt;# track all files in repo
&lt;/span&gt;&lt;span class="n"&gt;git&lt;/span&gt; &lt;span class="n"&gt;add&lt;/span&gt; &lt;span class="p"&gt;.&lt;/span&gt; 
&lt;span class="c1"&gt;# check tracked files status
&lt;/span&gt;&lt;span class="n"&gt;git&lt;/span&gt; &lt;span class="n"&gt;status&lt;/span&gt;
&lt;span class="c1"&gt;# take snapshot of files with message
&lt;/span&gt;&lt;span class="n"&gt;git&lt;/span&gt; &lt;span class="n"&gt;commit&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;m&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;My message&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
&lt;span class="c1"&gt;#view commit history
&lt;/span&gt;&lt;span class="n"&gt;git&lt;/span&gt; &lt;span class="n"&gt;log&lt;/span&gt;
&lt;span class="c1"&gt;# add remote repo
&lt;/span&gt;&lt;span class="n"&gt;git&lt;/span&gt; &lt;span class="n"&gt;remote&lt;/span&gt; &lt;span class="n"&gt;add&lt;/span&gt; &lt;span class="n"&gt;remote&lt;/span&gt; &lt;span class="n"&gt;origin&lt;/span&gt; &lt;span class="n"&gt;https&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="o"&gt;//&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;URL&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;to&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;remote&lt;/span&gt;
&lt;span class="c1"&gt;# Overwrite default branch
&lt;/span&gt;&lt;span class="n"&gt;git&lt;/span&gt; &lt;span class="n"&gt;branch&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;M&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;branch_name&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="c1"&gt;# Push to remote
&lt;/span&gt;&lt;span class="n"&gt;git&lt;/span&gt; &lt;span class="n"&gt;push&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;u&lt;/span&gt; &lt;span class="n"&gt;origin&lt;/span&gt; &lt;span class="n"&gt;main&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



</description>
      <category>git</category>
      <category>versioncontrol</category>
      <category>github</category>
      <category>code</category>
    </item>
    <item>
      <title>LDAP (Lightweight Directory Access Protocol</title>
      <dc:creator>Grace Valerie</dc:creator>
      <pubDate>Sun, 13 Oct 2024 16:03:26 +0000</pubDate>
      <link>https://dev.to/valgrace/ldap-lightweight-directory-access-protocol-i3m</link>
      <guid>https://dev.to/valgrace/ldap-lightweight-directory-access-protocol-i3m</guid>
      <description>&lt;p&gt;LDAP is the standard TCP/IP stack protocol that is used to store and query information from a hierarchical directory. It is an alternative to X.500 Directory service protocol which is more resource-intensive. LDAP is often used for SSO authentication and storage. By standard LDAP uses TCP port 389 for unencrypted communication and TLS port 636 over an encrypted channel.&lt;/p&gt;

&lt;h3&gt;
  
  
  How Does LDAP work?
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;Client starts an LDAP session through the dedicated TCP port.&lt;/li&gt;
&lt;li&gt;(Optional) Read and modify the session option values.&lt;/li&gt;
&lt;li&gt;Establish a connection to the LDAP server or explicitly bind to the server with a privileged  authenticated client using one of the binding functions.&lt;/li&gt;
&lt;li&gt;Submit a query to an email server or establish a connection to a printer. The server receives the query and returns the corresponding information to the user.&lt;/li&gt;
&lt;li&gt;After completion, close the connection to the LDAP server.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;em&gt;LDAP unlike most modern http-based protocols, uses persistent connections which can live for days when communication with a directory server.&lt;/em&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Advantages of Using LDAP
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;It is a mature protocol which keeps on evolving. It is a critical component of most large enterprises therefore the need to maintain revisions and update standards of the protocol.&lt;/li&gt;
&lt;li&gt;LDAP is a lightweight version of the X.500 protocol but is also very lightweight compared to other modern day protocols.&lt;/li&gt;
&lt;li&gt;LDAP is secure and is often used to store usernames, passwords and other sensitive information. But its security is subject to its implementation. It is important to follow best practices when adopting this protocol such as:

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;&lt;em&gt;establishing an access control policy.&lt;/em&gt;&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;em&gt;maintaining multiple copies of the directory data.&lt;/em&gt;&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;em&gt;encrypting sensitive information such as passwords.&lt;/em&gt;&lt;/strong&gt; &lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Components of LDAP
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Attribute&lt;/strong&gt;: the data in the LDAP system is stored in key-value pairs known as attributes. You can set an attributes value by separating the name and the value using a colon and a space. e.g.&lt;br&gt;
&lt;/p&gt;

&lt;p&gt;&lt;code&gt;mail: johndoe@gmail.com&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;p&gt;Use an equal's sign to refer to an attribute and its data without setting it. e.g.&lt;br&gt;
&lt;/p&gt;

&lt;p&gt;&lt;code&gt;mail=johndoe@gmail.com&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;p&gt;The most commonly used attributes include:&lt;br&gt;
                - &lt;strong&gt;&lt;em&gt;ou&lt;/em&gt;&lt;/strong&gt;: Organizational Unit&lt;br&gt;
                - &lt;strong&gt;_ dn_&lt;/strong&gt;: distinguished name&lt;br&gt;
                - &lt;strong&gt;&lt;em&gt;cn&lt;/em&gt;&lt;/strong&gt;: common name&lt;br&gt;
                - &lt;strong&gt;&lt;em&gt;description&lt;/em&gt;&lt;/strong&gt;&lt;br&gt;
                - &lt;strong&gt;&lt;em&gt;dc&lt;/em&gt;&lt;/strong&gt;: domain component&lt;br&gt;
                - &lt;strong&gt;&lt;em&gt;givenName&lt;/em&gt;&lt;/strong&gt;: first name&lt;br&gt;
                - &lt;strong&gt;&lt;em&gt;mail&lt;/em&gt;&lt;/strong&gt;: e-mail address&lt;br&gt;
                - &lt;strong&gt;&lt;em&gt;sn&lt;/em&gt;&lt;/strong&gt;: surname&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Entries&lt;/strong&gt;: an entry is a collection of attributes which are associated to or describe something. An entry could be a user in your system. Think of it as a row in a relational database. Each entry consists of:&lt;br&gt;
       - a distinguished name (uniquely identifies a specific entry in the DIT hierarchy&lt;br&gt;
       - a collection of attributes (they hold the data for the entry)&lt;br&gt;
       - a collection of object classes (they indicate what kind of object an entry represents e.g. information about a device or person)&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;dn: ou=Users,dc=example,dc=com,uid=jd001
objectClass: EntUsers
cn: Jane Doe
sn: Doe
mail: jdoe@example.com
uid: jd001
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Search Filters&lt;/strong&gt;: used to define the criteria for identifying entries that contain certain kinds of information. &lt;br&gt;
&lt;strong&gt;LDAP URLS&lt;/strong&gt;: this URL contains different pieces of information that can reference a directory server or a search criteria. &lt;/p&gt;

&lt;h3&gt;
  
  
  Primary Operators of LDAP
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;Add: Insert a new entry into the directory.&lt;/li&gt;
&lt;li&gt;Modify: change existing directory entries.&lt;/li&gt;
&lt;li&gt;Bind: authenticate and connect the LDAP client to the server.&lt;/li&gt;
&lt;li&gt;Delete: Remove directory entries.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;LDAP is used by Microsoft's Active Directory and other directory servers such as OpenLDAP and Red Hat Directory Server. To setup LDAP within an enterprise, you need a directory server, users with different permissions, directory data that can be queried and an LDAP client application.&lt;br&gt;
          -  &lt;/p&gt;

</description>
      <category>cybersecurity</category>
      <category>ldap</category>
      <category>python</category>
      <category>log4j</category>
    </item>
    <item>
      <title>ProxyChaining</title>
      <dc:creator>Grace Valerie</dc:creator>
      <pubDate>Wed, 31 Jul 2024 14:09:12 +0000</pubDate>
      <link>https://dev.to/valgrace/proxychaining-1c86</link>
      <guid>https://dev.to/valgrace/proxychaining-1c86</guid>
      <description>&lt;p&gt;In a world where digital privacy is a myth, achieving total anonymity has been a top concern for many organizations and individuals. One technique that enables this is using proxychains. The real identity of your original machine is obfuscated by bouncing your internet traffic through multiple proxy servers. &lt;/p&gt;

&lt;h2&gt;
  
  
  Definition Of Proxy Chaining
&lt;/h2&gt;

&lt;p&gt;Proxy chaining is a more intensive masking technique that involves hiding a proxy behind another proxy and using as many proxies in the chain as needed.&lt;/p&gt;

&lt;h2&gt;
  
  
  Benefits of using Proxychains
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Use of proxychains can make it possible to bypass firewall restrictions and access to resources when conducting reconnaissance without being detected.&lt;/li&gt;
&lt;li&gt;Proxychains in combination with other applications such as Nmap and pivoting tools like metasploit can be used to scan networks that are connected to a compromised network. &lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Using Proxychains
&lt;/h2&gt;

&lt;p&gt;This is a walkthrough on how to set up proxychains on a Kali Linux system. We will be using proxychains-ng instead of proxychains which is an enhanced proxychains project with improved functionality.&lt;/p&gt;

&lt;h3&gt;
  
  
  Installation
&lt;/h3&gt;

&lt;p&gt;Proxychains-ng comes pre-installed on kali-linux machines. You can confirm this with the command&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;proxychains4
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you get the following response then proxychains is already installed on your machine.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Focwxzxoqyh96qul9vgg3.PNG" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Focwxzxoqyh96qul9vgg3.PNG" alt="Check if proxychains is installed" width="610" height="133"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You can also install it using apt with the following command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;sudo apt install proxychains4
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Configuration
&lt;/h3&gt;

&lt;p&gt;You can use nano or vi to edit the configuration. In this case we will be changing the chain option and adding some proxies to the chain.&lt;/p&gt;

&lt;p&gt;Open the configuration file using the command&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;sudo nano /etc/proxychains4.conf
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;OR&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;sudo vi /etc/proxychains4.conf
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The editor opens. Scroll down to "dynamic_chain" option and uncomment it then further down to "strict_chain" and comment it. This will enable the dynamic_chain and disable strict_chain.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fhyn184ihyem8u1oj690x.PNG" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fhyn184ihyem8u1oj690x.PNG" alt="Enable dynamic chain" width="560" height="423"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  Chaining Options
&lt;/h4&gt;

&lt;p&gt;~ &lt;strong&gt;Dynamic chain:&lt;/strong&gt; the proxies used when routing requests changes dynamically and skips non-functional proxies.&lt;br&gt;
~ &lt;strong&gt;Strict chain:&lt;/strong&gt; all specified proxies are used in the order in which they are chained.&lt;br&gt;
~ &lt;strong&gt;Round Robin:&lt;/strong&gt; the chain assumes a circular connection between all proxies. With each request, the next proxy in the list is connected to until all the proxies in the chain are utilized. When the end of the chain is reached, then the next request connects to the first proxy in the list.&lt;br&gt;
~ &lt;strong&gt;Random chain:&lt;/strong&gt; you can specify the number of proxies to use in the request and the chain creates a random combination of proxies for the request. &lt;br&gt;
Scroll down to the bottom of the file to add proxies to your proxychain. You will find an existing loopback address using SOCKS4&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F303v8b1ehzyjywguxnfy.PNG" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F303v8b1ehzyjywguxnfy.PNG" alt="proxy list" width="531" height="126"&gt;&lt;/a&gt; which you need to comment out before adding new proxies. The proxies are specified in the sequence&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;type&amp;gt; &amp;lt;host&amp;gt; &amp;lt;port&amp;gt; [username password]
// some proxies do not have usernames or passwords
// types include SOCKS4, SOCKS5, HTTP/HTTPS
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Exit from the editor and you are now ready to use the proxychain. Test if its working with the command&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ proxychains4 curl ipinfo.io
$ // returns public ip address of the connected proxy as response
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffsyms2hddt562va4qkqm.PNG" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffsyms2hddt562va4qkqm.PNG" alt="pi address info" width="630" height="322"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;To connect to a browser, run the command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ proxychains4 firefox google.com
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



</description>
      <category>cybersecurity</category>
      <category>proxy</category>
      <category>linux</category>
      <category>tor</category>
    </item>
    <item>
      <title>The Ultimate CSS Testing Toolbox</title>
      <dc:creator>Grace Valerie</dc:creator>
      <pubDate>Sun, 24 Sep 2023 14:24:49 +0000</pubDate>
      <link>https://dev.to/valgrace/the-ultimate-css-testing-toolbox-4n2m</link>
      <guid>https://dev.to/valgrace/the-ultimate-css-testing-toolbox-4n2m</guid>
      <description>&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;Frontend testing is not often considered during the development process. It can be challenging to test front-end interfaces and style-sheets but regardless this process will ensure you create quality interfaces.&lt;br&gt;
There are four types of testing techniques commonly used, namely:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Syntax testing.&lt;/li&gt;
&lt;li&gt;Regression testing/ Reference Testing.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This article covers the different types of testing techniques and how to use different tools.&lt;/p&gt;
&lt;h2&gt;
  
  
  Prerequisites
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Familiarity with HTML, CSS and JavaScript.&lt;/li&gt;
&lt;li&gt;Have npm (node package manager) installed locally on your editor.&lt;/li&gt;
&lt;/ol&gt;
&lt;h2&gt;
  
  
  Regression Testing / Reference Testing
&lt;/h2&gt;

&lt;p&gt;This type of testing is generally used in software development and is applied to modified code to check if bugs and errors are introduced in the codebase. CSS regression testing tests for breaking changes on your interface when CSS style is modified.&lt;/p&gt;
&lt;h3&gt;
  
  
  Regression Testing Tools
&lt;/h3&gt;

&lt;p&gt;There are a number of available tools that are used to automate CSS regression tests.&lt;/p&gt;
&lt;h4&gt;
  
  
  BackstopJS
&lt;/h4&gt;

&lt;p&gt;BackstopJS is an automated visual regression testing tool for web user interfaces. It compares DOM elements screenshots over time. Backstop can be integrated with the playwrite engine and pupetteer.  &lt;/p&gt;
&lt;h4&gt;
  
  
  How To Use BackstopJs
&lt;/h4&gt;

&lt;ol&gt;
&lt;li&gt;Install the globally available backstopjs package.
&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;npm &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-g&lt;/span&gt; backstopjs
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;ol&gt;
&lt;li&gt;Create a default configuration file in your current working directory.
&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;backstop init
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;The above command creates a &lt;strong&gt;backstop.json&lt;/strong&gt; file in your root folder. When BackstopJS is invoked, it looks for this file. a folder named backstop_data is also created. It contains playwrite and puppeteer scripts in subfolders.&lt;/p&gt;
&lt;h5&gt;
  
  
  Configuration file (backstop.json) content properties.
&lt;/h5&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"backstop_default"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"viewports"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"label"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"phone"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"width"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;320&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"height"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;480&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"label"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"tablet"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"width"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1024&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"height"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;768&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"onBeforeScript"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"puppet/onBefore.js"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"onReadyScript"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"puppet/onReady.js"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"scenarios"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"label"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"BackstopJS Homepage"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"cookiePath"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"backstop_data/engine_scripts/cookies.json"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"url"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"https://garris.github.io/BackstopJS/"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"referenceUrl"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;""&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"readyEvent"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;""&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"readySelector"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;""&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"delay"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"hideSelectors"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[],&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"removeSelectors"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[],&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"hoverSelector"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;""&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"clickSelector"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;""&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"postInteractionWait"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"selectors"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[],&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"selectorExpansion"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"expect"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"misMatchThreshold"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;0.1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"requireSameDimensions"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"paths"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"bitmaps_reference"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"backstop_data/bitmaps_reference"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"bitmaps_test"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"backstop_data/bitmaps_test"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"engine_scripts"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"backstop_data/engine_scripts"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"html_report"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"backstop_data/html_report"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"ci_report"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"backstop_data/ci_report"&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"report"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"browser"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"engine"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"puppeteer"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"engineOptions"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"args"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"--no-sandbox"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"asyncCaptureLimit"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"asyncCompareLimit"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;50&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"debug"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"debugWindow"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;id&lt;/strong&gt;: Used for naming screenshots that you want to share reference files with teammates.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;viewports&lt;/strong&gt;: This property is an array of screen sies that your DOM objects will be tested against.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;scenarios&lt;/strong&gt;: This is the setup for your actual tests. It should contain a label and URL. Other sub-properties are optional. The URL is an absolute path to your webpage or local path. The label is a screenshot name identifier.
&lt;/li&gt;
&lt;/ul&gt;
&lt;h5&gt;
  
  
  Define a scenario
&lt;/h5&gt;

&lt;p&gt;The scenario property is an array where you modify your tests. CSS selectors are mostly used where you can specify click and hover events. Consider the following scenario:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="nl"&gt;"scenarios"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"label"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Login Page"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"url"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"http://localhost:3000/login"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"referenceUrl"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"https://anypay-28455.web.app/login"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"delay"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;30&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;      
      &lt;/span&gt;&lt;span class="nl"&gt;"clickSelector"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;".btn"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"selectors"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="s2"&gt;".formStyle"&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"selectorExpansion"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"misMatchThreshold"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;0.45&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"requireSameDimensions"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;

  &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Specifying a referenceUrl helps to create a reference file over which your test file is tested against. The refence URL can be a production environment URL. Otherwise leave the value as empty to set the url value as reference value by default. &lt;br&gt;
Run the following command to create a reference file.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;backstop reference
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A &lt;strong&gt;bitmaps_reference&lt;/strong&gt; file is created.&lt;br&gt;
After the reference file is created, run the test.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;backstop &lt;span class="nb"&gt;test&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;When the test is done, results for number of passed and failed tests are return. Results can also be viewed on the browser. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fajqgjei53ums9ifbbgy4.PNG" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fajqgjei53ums9ifbbgy4.PNG" alt="test results" width="800" height="304"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4nhe8bbknfwfavev4zx2.PNG" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4nhe8bbknfwfavev4zx2.PNG" alt="test scrubber" width="592" height="487"&gt;&lt;/a&gt;&lt;br&gt;
Use the scrubber tool to view the difference when the red vertical line is moved. &lt;/p&gt;

&lt;p&gt;If satisfied with the results, approve the test scenario reports. Your test batch images will now be used as the reference points.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;backstop approve
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Learn more about &lt;a href=""&gt;Backstop&lt;/a&gt; from their GitHub page.&lt;/p&gt;

&lt;p&gt;Other regression testing tools include CSSCritic, Spectre, Wraith, Gemini and Reg-cli.&lt;/p&gt;

&lt;h4&gt;
  
  
  Syntax Testing
&lt;/h4&gt;

&lt;p&gt;Syntax testing analyzes your CSS code to flag errors that break any syntax rules, which may in turn break the styling for your web page. Linting tools are used for this purpose. &lt;/p&gt;

&lt;h4&gt;
  
  
  Advantages of Using CSS Linting Tools
&lt;/h4&gt;

&lt;ol&gt;
&lt;li&gt;Error detection: CSS linters helps to identify such as incorrect selector syntax, misspelled property names and invalid selector values.&lt;/li&gt;
&lt;li&gt;Enforcing coding standards: CSS linters can be configured to follow specific standards according to your preferred guidelines.&lt;/li&gt;
&lt;/ol&gt;

&lt;h4&gt;
  
  
  Simple Command Line CSS Linting Tool
&lt;/h4&gt;

&lt;ol&gt;
&lt;li&gt;Install csslint from your command line.
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;npm &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-g&lt;/span&gt; csslint
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;Change directory to the folder where your css file is.
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;cd &lt;/span&gt;your_folder_name
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;Run "csslint" command on your CSS file.
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;  &lt;span class="nv"&gt;$ &lt;/span&gt;csslint css_file_name.css
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A list of potential issues are returned in the command line. &lt;/p&gt;

&lt;h5&gt;
  
  
  Example
&lt;/h5&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fl65wlmw5d7wzpngmqeza.PNG" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fl65wlmw5d7wzpngmqeza.PNG" alt="csslint" width="443" height="416"&gt;&lt;/a&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fr8un2yhlg5krir5pgboz.PNG" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fr8un2yhlg5krir5pgboz.PNG" alt="csslint2" width="480" height="208"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h5&gt;
  
  
  Potential Issues Identified
&lt;/h5&gt;

&lt;ol&gt;
&lt;li&gt;Too many font-size declarations.&lt;/li&gt;
&lt;li&gt;Don't use IDs in selectors.&lt;/li&gt;
&lt;li&gt;Heading (h3) should not be qualified. &lt;/li&gt;
&lt;li&gt;Rule doesn't have all its properties in alphabetical order.&lt;/li&gt;
&lt;li&gt;Fallback background-color (hex or RGB) should precede RGBA background-color.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;When CSS lint identifies these issues, it's easier to fix and adhere to the correct syntax.  &lt;/p&gt;

&lt;h4&gt;
  
  
  Stylelint
&lt;/h4&gt;

&lt;p&gt;This is a powerful linting tool as it can:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;automatically fix issues&lt;/li&gt;
&lt;li&gt;support shareable configurations&lt;/li&gt;
&lt;li&gt;be customized to your fit your preferences.
Stylelint can be installed using npm with the following command:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;npm init stylelint
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A new config file is created named &lt;em&gt;&lt;strong&gt;".stylelintrc.json"&lt;/strong&gt;&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;Run stylelint with:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;npx stylelint &lt;span class="s2"&gt;"**/*.css"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A list of errors that violate the syntax rules are displayed on the command line such as:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fpseswwxo0dtypitlwhd6.PNG" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fpseswwxo0dtypitlwhd6.PNG" alt="stylelint" width="759" height="111"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;After running Stylelint, proceed to customize its &lt;a href=""&gt;configuration&lt;/a&gt; to best suit your needs.&lt;/p&gt;

&lt;h3&gt;
  
  
  Conclusion
&lt;/h3&gt;

&lt;p&gt;Testing CSS code can be valuable to your web development workflow as it improves CSS code quality and consistency. To achieve comprehensive test coverage, combine regression testing tools with the syntax testing tools and also perform manual tests. Consider integrating tests into your Continuous Integration pipeline to run them automatically when changes are made.    &lt;/p&gt;

</description>
      <category>webdev</category>
      <category>css</category>
      <category>testing</category>
      <category>cicd</category>
    </item>
    <item>
      <title>Git Branching Strategies: How To Manage Your Codebase Effectively</title>
      <dc:creator>Grace Valerie</dc:creator>
      <pubDate>Wed, 13 Sep 2023 06:27:13 +0000</pubDate>
      <link>https://dev.to/valgrace/git-branching-strategies-how-to-manage-your-codebase-effectively-32lm</link>
      <guid>https://dev.to/valgrace/git-branching-strategies-how-to-manage-your-codebase-effectively-32lm</guid>
      <description>&lt;p&gt;In modern software and DevOps teams, version control systems are the powerhouse when it comes to delivering software. they are capable of managing source code changes and tracking code change history. As much as version control systems are effective, working on big teams with simultaneous activity can make it difficult to create branches or even merge code. This is why we need a branching strategy.  &lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;&lt;em&gt;A branching strategy is used by software development teams to design a proper way in which branches are created and code is merged.&lt;/em&gt;&lt;/strong&gt; &lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Prerequisites
&lt;/h2&gt;

&lt;p&gt;The only requirement before reading this article is that you have a fair understanding of version control, git and branching in git.&lt;/p&gt;

&lt;h2&gt;
  
  
  Sub-topics
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Why should you implement a branching strategy&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Factors to Consider When Choosing a Branching Strategy.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Types Of Branching Strategies.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Why should you implement a branching strategy?
&lt;/h2&gt;

&lt;p&gt;A branching strategy is essential for any large-scale project as it improves collaboration and accelerates the delivery process and business value. Distributed version control systems such as git gives you the flexibility to use different branching strategies, unlike centralized systems. &lt;/p&gt;

&lt;h2&gt;
  
  
  Factors to Consider When Choosing Branching Strategy?
&lt;/h2&gt;

&lt;p&gt;The branch strategy you use will mainly be influenced by the project requirements. When picking a strategy, ask yourself the following questions:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;How big is the size of the team?&lt;/li&gt;
&lt;li&gt;What is the complexity and size of the project?&lt;/li&gt;
&lt;li&gt;How often do you make deployments?&lt;/li&gt;
&lt;li&gt;Will your development workflow fit in with the strategy? &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In the following section, I will cover the different types of strategies that are commonly used. Remember that whichever strategy you choose it is not fixed, and you can refine it as your project needs change.  &lt;/p&gt;

&lt;h2&gt;
  
  
  Types of Branching Strategies.
&lt;/h2&gt;

&lt;p&gt;We have two most commonly used branching strategies namely, feature branching and trunk-based development. There are other types as well such as gitflow, github flow, release branching and more. &lt;/p&gt;

&lt;h2&gt;
  
  
  Feature-branching
&lt;/h2&gt;

&lt;p&gt;Feature branching method requires the developer to create a new feature branch for every new feature and bugs. In this way you can isolate your work in progress from your completed work in the main branch. This technique makes it easy to access and review the history of changes made after writing commits and opening pull requests. Here's how to implement this workflow:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Identify and assign features for developers to work on. Consider if the developers can work on these features independently with minimal conflict.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Let each developer create a feature branch based off the main/master branch. Developers can now work on their respective features in the branches they created without interference from others.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Implement code review in your workflow whenever a pull request or merge request is made.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;After code review and merge is done, the feature branch should be deleted to keep the repository clean.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Repeat the process for each feature. as best practice, use a  &lt;a href=""&gt;naming convention&lt;/a&gt; for your feature branches.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F3t4o5tfdp75czgcjigy6.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F3t4o5tfdp75czgcjigy6.png" alt="feature branching diagram" width="800" height="217"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Trunk-Based Development
&lt;/h2&gt;

&lt;p&gt;This branching strategy enforces continuous integration where changes can be released frequently, and automated tests run after each commit. Trunk based development encourages developers to merge changes to the trunk (master) as often as possible thus eliminating the need for long lived branches that can cause merge conflicts.&lt;/p&gt;

&lt;h4&gt;
  
  
  Best Practices
&lt;/h4&gt;

&lt;ol&gt;
&lt;li&gt;Small incremental changes - commits should be made daily which requires short lived branches. When teams break down work into smaller sections it makes it easier to commit daily and review quickly. &lt;/li&gt;
&lt;li&gt;Feature toggles - by creating feature flags, developers can deactivate unfinished features and still make changes then activate the feature when done.&lt;/li&gt;
&lt;li&gt;Automated testing and code reviews - implement a code review system where committed changes are reviewed as fast as possible. In any modern software project, regular testing is part of the continuous integration process. It helps teams to discover and resolve bugs early, which can lead to technical debt.&lt;/li&gt;
&lt;li&gt;Delete inactive branches or once a branch is merged. Ensure that there are no more than three branches in your repository.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Trunk based strategy is suitable for any team size and complex projects. Its success will solely depend on how it is implemented and if developers embrace it. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F8pt6kkf9u7i2dn8cclbp.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F8pt6kkf9u7i2dn8cclbp.png" alt=" " width="771" height="491"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Gitflow Branching Strategy
&lt;/h2&gt;

&lt;p&gt;Gitflow strategy is a way for developers to work in parallel and away from the master branch by using feature branches. This workflow consists of five different branches.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Master branch: This is the main branch that is created at the start of the project. Commits made in this branch are tagged with a version number. &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Develop: This branch is also a master branch where changes from the feature branch are integrated. Feature branches are branched off the develop branch.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Feature branch: Feature branches are where developers create and develop new features.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Release - This branch is created off the develop branch when you are ready to release new features.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Hotfix - used for emergency bug fixes.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Gitflow is most suitable for software that are explicitly versioned to allow for roll backs. All versions are in production which means they need continuous support. This strategy can be used when developing operating systems or packages but not web applications. &lt;/p&gt;

</description>
      <category>git</category>
      <category>gitflow</category>
      <category>devops</category>
      <category>trunkbaseddevelopment</category>
    </item>
    <item>
      <title>The Ultimate Chrome Tutorial</title>
      <dc:creator>Grace Valerie</dc:creator>
      <pubDate>Sat, 09 Sep 2023 18:03:13 +0000</pubDate>
      <link>https://dev.to/valgrace/the-ultimate-chrome-tutorial-4iki</link>
      <guid>https://dev.to/valgrace/the-ultimate-chrome-tutorial-4iki</guid>
      <description>&lt;p&gt;Chrome is a cross-platform created by google that hosts search engines which are used to search for information over the internet which is then returned as a list of web pages that match the search uery.&lt;/p&gt;

&lt;h2&gt;
  
  
  How to Choose a Search Engine In Chrome
&lt;/h2&gt;

&lt;p&gt;On the top right side of the screen click the three dots to go to settings.&lt;br&gt;
a left side menu appears on the settings page, click on search engine option.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fnzm4y3o0sb5uygw9z7h1.PNG" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fnzm4y3o0sb5uygw9z7h1.PNG" alt="settings" width="800" height="373"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Select your preferred search engine from the drop down list as indicated in the diagram.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fsnyczffoj0sbzcfvkhg7.PNG" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fsnyczffoj0sbzcfvkhg7.PNG" alt="Search dropdown" width="800" height="267"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  How To Search
&lt;/h2&gt;

&lt;p&gt;To successfully search for any information on the internet via a web browser, you will need an internet connection.&lt;/p&gt;

&lt;p&gt;On the new tab, type the text you would like to search for in the input section. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fugh04b823dvxkmd4fxku.PNG" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fugh04b823dvxkmd4fxku.PNG" alt="Search article" width="790" height="251"&gt;&lt;/a&gt; &lt;/p&gt;

&lt;p&gt;Press enter to view your search results.&lt;br&gt;
The search engine tries as much as possible to give to the best matching results.&lt;/p&gt;

&lt;p&gt;Your search results will display a list of websites with the keyword you typed for. Through search engine mechanisms the displayed information will also contain additional information as provided by a specific website. This way you can determine if the result is the one you are looking for before opening the website.&lt;/p&gt;

&lt;p&gt;Example.&lt;br&gt;
On the search bar enter the input text appwrite.&lt;br&gt;
The search results will come in different formats and you can choose which format you want. By default you will have the all results option selected.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fwf9h9srh5o82xxnqgypu.PNG" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fwf9h9srh5o82xxnqgypu.PNG" alt="Search filter" width="718" height="138"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
    </item>
  </channel>
</rss>
