<?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: Edidiong Etuk</title>
    <description>The latest articles on DEV Community by Edidiong Etuk (@edeediong).</description>
    <link>https://dev.to/edeediong</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%2F129803%2Fd0561ab9-00c6-4131-b09a-53c98ed1d34b.png</url>
      <title>DEV Community: Edidiong Etuk</title>
      <link>https://dev.to/edeediong</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/edeediong"/>
    <language>en</language>
    <item>
      <title>GraphQL and Python Series (Expressive Introduction) </title>
      <dc:creator>Edidiong Etuk</dc:creator>
      <pubDate>Sun, 28 Jun 2020 22:30:27 +0000</pubDate>
      <link>https://dev.to/edeediong/graphql-and-python-series-expressive-introduction-54ii</link>
      <guid>https://dev.to/edeediong/graphql-and-python-series-expressive-introduction-54ii</guid>
      <description>&lt;h1&gt;
  
  
  GraphQL and Python Series (Expressive Introduction)
&lt;/h1&gt;

&lt;p&gt;This is part 1 of an ongoing series to introduce you to using GraphQL and Python. Hopefully, at the end of this series, you will be able to build a GraphQL Backend with Django and Graphene.&lt;/p&gt;

&lt;h2&gt;
  
  
  GraphQL Introductions
&lt;/h2&gt;

&lt;p&gt;GraphQL is a strongly typed language and is an alternative to REpresentational Transfer(REST).&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Missing explanation: Try and explain why GraphQL was created and why it's an alternative to REST. PayPal Engineering Medium article can help.&lt;br&gt;
An example of a GraphQL query us as follows:&lt;br&gt;
&lt;/p&gt;
&lt;/blockquote&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight graphql"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="n"&gt;allFilms&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="n"&gt;films&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="n"&gt;title&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="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h3&gt;
  
  
  GraphQL Type Schema
&lt;/h3&gt;

&lt;p&gt;We'd mostly be using two types in GraphQL, the Object Type and the Scalar Type.&lt;br&gt;
Object types can contain their own set of subfields, generally speaking, they have to be an object.&lt;/p&gt;

&lt;p&gt;Scalar types are built-in GraphQL data types, and they are five in number: integers, floats, strings, booleans and ids(these are unique strings). Now, these are the standard five, but they can be extended and still be Scalar Types as we will in this article.&lt;/p&gt;
&lt;h3&gt;
  
  
  CRUD Operations in GraphQL
&lt;/h3&gt;

&lt;p&gt;Create Read Update Delete(CRUD) functionalities are done in GraphQL using two operations: Query and Mutations. Just like we've done above, reading data(R) is done normally using queries. But to write or change data, we need a GraphQL operation called Mutation.&lt;br&gt;
In summary, CUD - is covered by mutations while R - is covered by queries. The codes below are examples of using mutation to create, update and delete objects respectively&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight graphql"&gt;&lt;code&gt;&lt;span class="k"&gt;mutation&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="n"&gt;createBaby&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;bodyInfo&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="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="s2"&gt;"Edidiong"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="n"&gt;votes&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1&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="n"&gt;name&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="n"&gt;votes&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="k"&gt;mutation&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="n"&gt;upvote&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Edidiong"&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="n"&gt;name&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="n"&gt;votes&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="k"&gt;mutation&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="n"&gt;remove&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Edidiong"&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="n"&gt;name&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="n"&gt;votes&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;You notice when reading data, you don't need to use query keyword but in creating, updating or deleting data, you use the mutation keyword so the engine knows you're doing a mutation.&lt;/p&gt;

&lt;h2&gt;
  
  
  Intro to Graphene/GraphQL In Python
&lt;/h2&gt;

&lt;p&gt;By now you have seen how to do queries and mutations in Vanilla GraphQL(borrowing the word Vanilla from JavaScript), let's see how to perform GraphQL in Python.&lt;/p&gt;

&lt;h3&gt;
  
  
  Query Operation
&lt;/h3&gt;

&lt;p&gt;To create a query, you, first of all, need a root query(this point will be explained in the code session below). Also, GraphQL uses the OOP structure to work so if you're not familiar with OOP, you may find it difficult to follow.&lt;/p&gt;

&lt;h4&gt;
  
  
  Code
&lt;/h4&gt;

&lt;p&gt;Create a new file called &lt;code&gt;schema.py&lt;/code&gt; and rewrite these codes here into the file.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;uuid&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;json&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;datetime&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;datetime&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;graphene&lt;/span&gt;

&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;User&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;graphene&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ObjectType&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="nb"&gt;id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;graphene&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ID&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;default_value&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;uuid&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;uuid4&lt;/span&gt;&lt;span class="p"&gt;()))&lt;/span&gt;
    &lt;span class="n"&gt;username&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;graphene&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;String&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="n"&gt;created_at&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;graphene&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;DateTime&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;default_value&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;datetime&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;now&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;


&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Query&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;graphene&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ObjectType&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;users&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;graphene&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;List&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;User&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;limit&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;graphene&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Int&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
    &lt;span class="n"&gt;hello&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;graphene&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;String&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;resolve_hello&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;info&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="s"&gt;"world"&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;resolve_users&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;info&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;limit&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
            &lt;span class="n"&gt;User&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;id&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"1"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;username&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"Khalid"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;created_at&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;datetime&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;now&lt;/span&gt;&lt;span class="p"&gt;()),&lt;/span&gt;
            &lt;span class="n"&gt;User&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;id&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"2"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;username&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"Ann"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;created_at&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;datetime&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;now&lt;/span&gt;&lt;span class="p"&gt;()),&lt;/span&gt;
            &lt;span class="n"&gt;User&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;id&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"3"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;username&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"fred"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;created_at&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;datetime&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;now&lt;/span&gt;&lt;span class="p"&gt;()),&lt;/span&gt;
            &lt;span class="p"&gt;][:&lt;/span&gt;&lt;span class="n"&gt;limit&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;


&lt;span class="c1"&gt;# Query of users
&lt;/span&gt;&lt;span class="n"&gt;schema&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;graphene&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Schema&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;query&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;Query&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;auto_camelcase&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;schema&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;execute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="s"&gt;'''
    {
        users {
            id
            username
            createdAt
        }
    }
    '''&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;dict_result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;dict&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;.&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;items&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
&lt;span class="k"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;dict_result&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Let's break down the code above to grasp what was done.&lt;/p&gt;

&lt;h4&gt;
  
  
  User
&lt;/h4&gt;

&lt;p&gt;A &lt;code&gt;User&lt;/code&gt; class was created that inherited from the &lt;code&gt;graphene.ObjectType&lt;/code&gt;. Almost all of the GraphQL types you define will be object types(only a few percentages will be Scalar Types). Object types have a name, but most importantly describe their fields.&lt;/p&gt;

&lt;p&gt;So the &lt;code&gt;User&lt;/code&gt; class contains the id, username and date the account was created all. You  will notice id and username are default scalar types(the &lt;code&gt;.ID()&lt;/code&gt; and &lt;code&gt;.String()&lt;/code&gt;), we are adding &lt;code&gt;.DateTime()&lt;/code&gt; as a scalar type(Dive deep into the Graphene source code to see all available Scalar types).&lt;/p&gt;

&lt;h4&gt;
  
  
  Query
&lt;/h4&gt;

&lt;p&gt;Earlier, we learnt that to create a query in graphene, we first need a root query. The class &lt;code&gt;Query&lt;/code&gt; is that root query. We have two class attributes defined in the query: &lt;code&gt;hello&lt;/code&gt; and &lt;code&gt;users&lt;/code&gt;. More about the &lt;code&gt;hello&lt;/code&gt; query later.&lt;br&gt;
The &lt;code&gt;users&lt;/code&gt; attribute takes in the &lt;code&gt;User&lt;/code&gt; class and a &lt;code&gt;limit&lt;/code&gt; argument, these two are what we would use in our actual GraphQL query. The users' details will be returned in a &lt;code&gt;List&lt;/code&gt; structure.&lt;/p&gt;

&lt;p&gt;The methods we have created in this &lt;code&gt;Query&lt;/code&gt; class are called &lt;code&gt;resolvers&lt;/code&gt;. Resolvers are functions that resolves a value for a type or field in a schema. Simply put, resolvers are what return objects or scalar from our query. To name a resolver, it has to have the word &lt;code&gt;resolve_&lt;/code&gt; in its name(just like how &lt;a href="https://github.com/edeediong/Articles/blob/master/Embracing%20Pytest.md"&gt;Test Driven Development in Python&lt;/a&gt;) are. We also set a default value for the limit parameter.&lt;/p&gt;
&lt;h4&gt;
  
  
  Schema
&lt;/h4&gt;

&lt;p&gt;To execute the code we've written, we will use the Graphene &lt;code&gt;Schema&lt;/code&gt;. The graphene schema can execute operations(query, mutation and subscription) against the defined types. Looking up type definitions and answering questions about the types through introspection are advance use cases of the schema.&lt;br&gt;
The schema has a &lt;code&gt;query&lt;/code&gt; parameter which we will pass our class &lt;code&gt;Query&lt;/code&gt; into as an argument. This query argument is the entry point for fields to &lt;strong&gt;read&lt;/strong&gt; data in our Schema.&lt;/p&gt;
&lt;h4&gt;
  
  
  Execute
&lt;/h4&gt;

&lt;p&gt;To provide the result, we use the &lt;code&gt;execute&lt;/code&gt; method in the Schema class. In this method, we will provide the query in a GraphQL format but since we're using Python, it will be wrapped in a Block comment. In GraphQL, it is standard to use camelCase names. So our Fieldnames are transformed in Schema's TypeMap from snake_case to camelCase and this is made possible because of the &lt;code&gt;auto_camelcase&lt;/code&gt; argument and it set to &lt;code&gt;True&lt;/code&gt; by default.&lt;br&gt;
The effect is seen in our query as &lt;code&gt;created_at&lt;/code&gt; is changed to &lt;code&gt;createdAt&lt;/code&gt; following the &lt;code&gt;camelCase&lt;/code&gt; convention.&lt;/p&gt;
&lt;h4&gt;
  
  
  Result
&lt;/h4&gt;

&lt;p&gt;You should have a response like the image below&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Include The Result Image.&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;To better format the result, we use the &lt;code&gt;json.dumps&lt;/code&gt; method so as to use the &lt;code&gt;indent&lt;/code&gt; parameter in this method. Alter the print statement above to the one below and run it to see the newly formatted result.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;dumps&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;dict_result&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;indent&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Include The Result Image.&lt;/strong&gt;&lt;br&gt;
If you have a result similar to the image above, congratulations.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The limit parameter is by default set to &lt;code&gt;None&lt;/code&gt; so the output shows all the users in the resolver. If we set a limit to 1 as we do in the code below, we see it returns just a single query.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;schema&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;execute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="s"&gt;'''
    {
        users(limit: 1) {
            id
            username
            createdAt
        }
    }
    '''&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; The &lt;code&gt;(limit: 1)&lt;/code&gt; is used because of the &lt;code&gt;users&lt;/code&gt; attribute in the class &lt;code&gt;Query&lt;/code&gt;. We had defined &lt;code&gt;limit&lt;/code&gt; as a scalar type inside the users: which is what made &lt;code&gt;(limit: 1)&lt;/code&gt; work.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Also, we created a hello resolver. We will say this is our hello world in Graphene. To run the hello query, replace the previous query with the one below:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight graphql"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="n"&gt;hello&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;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Include The Result Image.&lt;/strong&gt;&lt;br&gt;
The image above is a result of the query.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;We have been able to understand everything there is about queries. Now let's move to mutations.&lt;/p&gt;

&lt;h3&gt;
  
  
  Mutation Operations
&lt;/h3&gt;

&lt;p&gt;Remember when we said to create queries we need a root query, in mutations, it's sorta different. The Mutation is a convenience type that helps us build a &lt;code&gt;Field&lt;/code&gt; which takes &lt;code&gt;Arguments&lt;/code&gt; and returns a &lt;code&gt;mutation Output ObjectType&lt;/code&gt;. This means to perform CUD operations, we need to pass arguments to a mutation. To pass in arguments to a mutation we need to pass in an inner Arguments class.&lt;/p&gt;

&lt;h4&gt;
  
  
  Code(mutation)
&lt;/h4&gt;

&lt;p&gt;Add these new classes into the &lt;code&gt;schema.py&lt;/code&gt; file but arrange the classes to be on top of another.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;CreateUser&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;graphene&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Mutation&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;user&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;graphene&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Field&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;User&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Arguments&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;username&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;graphene&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;String&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;


    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;mutate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;info&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;username&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="n"&gt;user&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;User&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;id&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"4"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;username&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;username&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;created_at&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;datetime&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;now&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;CreateUser&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;


&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Mutation&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;graphene&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ObjectType&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;create_user&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;CreateUser&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Field&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Also, comment out the previous schema and append this to the end of the file.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# Mutation
&lt;/span&gt;&lt;span class="n"&gt;schema&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;graphene&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Schema&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;query&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;Query&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;mutation&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;Mutation&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;schema&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;execute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="s"&gt;'''
    mutation {
        createUser(username: "Edidiong") {
            user {
                id
                username
                createdAt
            }
        }
    }
    '''&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Let's break down the code above to grasp what was done.&lt;/p&gt;

&lt;h4&gt;
  
  
  CreateUser
&lt;/h4&gt;

&lt;p&gt;The &lt;code&gt;CreateUser&lt;/code&gt; class inherits from graphene's &lt;code&gt;Mutation&lt;/code&gt; class and creates a Field that is available on an ObjectType. The ObjectType here is our &lt;code&gt;User&lt;/code&gt; class.&lt;/p&gt;

&lt;h4&gt;
  
  
  Arguments
&lt;/h4&gt;

&lt;p&gt;&lt;code&gt;Arguments&lt;/code&gt; inner class passes the attribute &lt;code&gt;username&lt;/code&gt; to the &lt;code&gt;CreateUser&lt;/code&gt; class and this username is gotten from the resolver. This attribute is a Scalar Type(String) and it's the arguments we use for the mutation Field.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;mutate&lt;/code&gt; method is a resolver method for the Mutation class. It performs data change and returns the output which in this case the &lt;code&gt;username&lt;/code&gt;, &lt;code&gt;id&lt;/code&gt; and &lt;code&gt;created_at&lt;/code&gt; are the data change and a new user is returned.&lt;/p&gt;

&lt;h4&gt;
  
  
  Mutation
&lt;/h4&gt;

&lt;p&gt;The Mutation class takes in the &lt;code&gt;CreateUser&lt;/code&gt; class and mounts it as a &lt;code&gt;Field&lt;/code&gt;. Like we know, almost all GraphQL types you define will be &lt;code&gt;ObjectType&lt;/code&gt;. Refer to the Mutation Operation header to understand what happens behind the engine of the &lt;code&gt;Mutation&lt;/code&gt; class.&lt;/p&gt;

&lt;h4&gt;
  
  
  Schema(mutation)
&lt;/h4&gt;

&lt;p&gt;We already know about the Schema class and &lt;code&gt;query&lt;/code&gt; parameter. The &lt;code&gt;mutation&lt;/code&gt; parameter describes the entry point for fields to &lt;em&gt;create, update or delete&lt;/em&gt; data in our API. We pass in the &lt;code&gt;Mutation&lt;/code&gt; class as an argument to the &lt;code&gt;mutation&lt;/code&gt; argument so as to perform CUD operations with it(in our case it's only Create we've done).&lt;/p&gt;

&lt;h4&gt;
  
  
  Execute(mutation)
&lt;/h4&gt;

&lt;p&gt;The execute in mutation also does the same thing as execute in query: to read the query from a GraphQL format into a Python format so as a result can be gotten.&lt;br&gt;
The only difference is the way to write the call. The &lt;code&gt;mutation&lt;/code&gt; keyword comes in just like we were told earlier in the article. From the previous Execute header, we understand how &lt;code&gt;(username: "Edidiong")&lt;/code&gt; comes about.&lt;/p&gt;

&lt;h4&gt;
  
  
  Result
&lt;/h4&gt;

&lt;p&gt;We should have a result similar to the image below.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Include The Result Image.&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  Subscription Operations
&lt;/h3&gt;

&lt;h2&gt;
  
  
  Next Steps
&lt;/h2&gt;

&lt;p&gt;Next, we will talk about Building GraphQL Backends with Django and Graphene. If you liked the article upvote and either drop a comment below or send me a &lt;a href="//edeediong@gmail.com"&gt;mail&lt;/a&gt;&lt;/p&gt;

</description>
      <category>graphql</category>
      <category>python</category>
    </item>
    <item>
      <title>Basics of Pytest</title>
      <dc:creator>Edidiong Etuk</dc:creator>
      <pubDate>Tue, 16 Jun 2020 13:25:32 +0000</pubDate>
      <link>https://dev.to/edeediong/understanding-pytest-1e0p</link>
      <guid>https://dev.to/edeediong/understanding-pytest-1e0p</guid>
      <description>&lt;p&gt;In the previous article I wrote about &lt;a href="https://dev.to/edeediong/using-travisci-to-write-better-python-codes-27kg"&gt;Linting with Travis in Python&lt;/a&gt;, we introduced pytest for checking lints, but question what is Pytest? Pytest is a testing framework just like the in-built unittest which allows us to write test codes using python. &lt;/p&gt;

&lt;h2&gt;
  
  
  Why We're Here
&lt;/h2&gt;

&lt;p&gt;Pytest doesn't force you to abandon the Python way of writing code, unlike python's inbuilt test module that forces you to follow the Java culture. This is because it is based on Erich Gamma's JUnit and Kent Beck's Smalltalk testing framework. We're here to embrace a new way of life in test-driven developments.&lt;/p&gt;

&lt;h2&gt;
  
  
  Getting Started with pytest
&lt;/h2&gt;

&lt;p&gt;Pytest is a command-line tool that discovers Python tests and executes them. It's easy to get started with. Follow these steps to continue:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Create a virtual environment using &lt;code&gt;python3 -m venv testing&lt;/code&gt; and activate it(Linux and Windows use different methods to activate the venv).&lt;/li&gt;
&lt;li&gt;Ensure you have pytest installed, use &lt;code&gt;pip install pytest&lt;/code&gt; if you haven't done so already.&lt;/li&gt;
&lt;li&gt;Ensure pytest is available in the command line using &lt;code&gt;pytest -h&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Create a file called test_basic.py, and add the following functions in it:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight python"&gt;&lt;code&gt;    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;test_dev&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
        &lt;span class="n"&gt;stdout&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"DEV Community"&lt;/span&gt;
        &lt;span class="k"&gt;assert&lt;/span&gt; &lt;span class="n"&gt;stdout&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="s"&gt;"DEV Community"&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;test_exponent&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
        &lt;span class="n"&gt;exponent&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;
        &lt;span class="k"&gt;assert&lt;/span&gt; &lt;span class="n"&gt;exponent&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;9&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Now on your terminal, run your test using &lt;code&gt;pytest test_basic.py&lt;/code&gt;&lt;br&gt;
You should see a result like below:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s---p6-rHE5--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/3fdpwbdi9fntjjnl9vpr.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s---p6-rHE5--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/3fdpwbdi9fntjjnl9vpr.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  Output
&lt;/h3&gt;

&lt;p&gt;If you have the output above, congratulations, you have successfully run your first test with Pytest, it's that easy. You can see how many tests passed and how many failed and also the line throwing the error.&lt;/p&gt;

&lt;p&gt;Also, the &lt;code&gt;test_basic.py .F [100%]&lt;/code&gt;. When a test runs successfully, It uses the period(full stop) to show that it didn't fail, but when it fails, it uses the F to show failure. This list shows you the outputs from a Pytest build:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;.&lt;/strong&gt; - test passed&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;F&lt;/strong&gt; - test failed&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;E&lt;/strong&gt; - Exception&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;s&lt;/strong&gt; - test skipped&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;x&lt;/strong&gt; - expected failure (broken now but will fix)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;X&lt;/strong&gt; - unexpected pass (should have failed)&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;
  
  
  Layouts And Conventions
&lt;/h2&gt;

&lt;p&gt;When testing with Pytest, there are few conventions you should follow:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;The testing directory needs to be named tests.&lt;/li&gt;
&lt;li&gt;Test files need to be prefixed or suffixed with test; for example, test_basic.py or basic_test.py&lt;/li&gt;
&lt;li&gt;Test functions need to be prefixed with &lt;code&gt;test_&lt;/code&gt;; for example &lt;code&gt;test_hello&lt;/code&gt;. If it is named &lt;code&gt;testhello.py&lt;/code&gt;, Pytest won't see it.&lt;/li&gt;
&lt;li&gt;Test classes need to be prefixed with Test; for example &lt;code&gt;TestCase&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;If test subdirectories don't have &lt;code&gt;__init__.py&lt;/code&gt;, you can't use the same filename in different directories.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;So the most basic structure of a project to be tested is as seen below;&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Project
\---proj
    |   proj_file.py
    |   __init__.py
    |
    \---test
            test_proj_file.py
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h2&gt;
  
  
  Differences with unittest
&lt;/h2&gt;

&lt;p&gt;Python has an inbuilt utility for testing called unittest module. Here are some of the differences.&lt;/p&gt;
&lt;h3&gt;
  
  
  Code Difference
&lt;/h3&gt;


&lt;div class="highlight"&gt;&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;unittest&lt;/span&gt;

&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;TestExponent&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;unittest&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;TestCase&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;test_exponent&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="n"&gt;exponent&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;
        &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;assertEquals&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;exponent&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;9&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;


&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;TestDev&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;unittest&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;TestCase&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;test_dev&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="n"&gt;stdout&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"DEV Community"&lt;/span&gt;
        &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;assertIs&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;stdout&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"DEV Community"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;In another directory, create a new python file called &lt;code&gt;test_basic&lt;/code&gt; and copy and paste the above code into it. Then run it with &lt;code&gt;python -m unittest&lt;/code&gt;.&lt;/p&gt;
&lt;h3&gt;
  
  
  Pythonic Culture
&lt;/h3&gt;

&lt;p&gt;Like we earlier said, the unittest uses a Java coding culture. What this means is unittest forces the use of classes and class inheritance. Python standardly isn't a strong OOP language so beginners and even intermediates may have a hard time using the unittest module. The unittest module focuses on OOP making testing an obstacle to newbies. For experienced developers, OOP isn't a problem but using classes and inheritance to write a simple test is absurd! Pytest follows Python's culture in making things simple(check out the Zen of Python: &lt;code&gt;import this&lt;/code&gt; in the python shell will show more.)&lt;/p&gt;
&lt;h3&gt;
  
  
  Multiple Assertions
&lt;/h3&gt;

&lt;p&gt;Once you inherit from TestCase, you are required to understand(and remember) most of the assertion methods used to test results. In our code difference session, we see we used two different asserts compared to the single &lt;code&gt;assert&lt;/code&gt; we used in our actual code. Some asserts can be found &lt;a href="https://docs.python.org/2/library/unittest.html#test-cases"&gt;here&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  Comparison Engine
&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;pytest&lt;/code&gt; provides a rich comparison engine on failures when compared to unittest. It's more like a verbose but pytest even has a verbose flag to see more of what your code is doing. That's some cool stuff if you ask me. Lol, for definition sake, verbose is: ...&lt;/p&gt;
&lt;h3&gt;
  
  
  Extendability
&lt;/h3&gt;

&lt;p&gt;Pytest is extendable, it's not limited like unittest. This means you can use pytest past its basic uses. You can alter its engine.&lt;/p&gt;
&lt;h3&gt;
  
  
  Summary of the differences
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;unittest is Non-PEP 8 compliant(Python's own culture)&lt;/li&gt;
&lt;li&gt;unittest is "Classy" - Matt Harrison&lt;/li&gt;
&lt;li&gt;So many assert methods to remember&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;
  
  
  Some Points To Note About Assert
&lt;/h2&gt;
&lt;h3&gt;
  
  
  How assert Works
&lt;/h3&gt;

&lt;p&gt;So far, we can say the pytest replaces the Java way with the Python way and also replaces over .. assert statements to just one assert. Pytest uses an &lt;code&gt;import hook&lt;/code&gt; (PEP 302) to rewrite assert statements by introspecting code(AST) runner has collected.&lt;/p&gt;
&lt;h3&gt;
  
  
  Careful Handling
&lt;/h3&gt;

&lt;p&gt;Don't wrap assertion in parentheses. Parentheses are by default a truthy tuple. Add the code below to our &lt;code&gt;test_basic.py&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight python"&gt;&lt;code&gt;
&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;test_almost_false&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="k"&gt;assert&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;False&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;You will get a warning like the one in the picture below.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--xRW3UA1Y--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/0o8okpoffa207jffxo7y.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--xRW3UA1Y--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/0o8okpoffa207jffxo7y.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Ability to specify a message
&lt;/h3&gt;

&lt;p&gt;You can specify a message in assert statements. Note for &lt;code&gt;test_almost_false&lt;/code&gt; function, once you specify a message, it changes from a failed test to pass with a warning. This isn't efficient and in subsequent articles, we will explain how to handle this expected failure. Reediting the &lt;code&gt;test_basic.py&lt;/code&gt; file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;test_dev&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="s"&gt;"""Checks if Hello World is the result."""&lt;/span&gt;
    &lt;span class="n"&gt;stdout&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"DEV Community"&lt;/span&gt;
    &lt;span class="k"&gt;assert&lt;/span&gt; &lt;span class="n"&gt;stdout&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="s"&gt;"DEV Community"&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;test_exponent&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="s"&gt;"""Checks if the exponential is equal 9."""&lt;/span&gt;
    &lt;span class="n"&gt;exponent&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt; &lt;span class="o"&gt;**&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;
    &lt;span class="k"&gt;assert&lt;/span&gt; &lt;span class="n"&gt;exponent&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;9&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"Value should be 9"&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;test_almost_false&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="k"&gt;assert&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;False&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;'Should be false'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

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



&lt;p&gt;We should have a result like an image below:&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--VfkB-xJV--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/1l2k2cd69mscm23srune.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--VfkB-xJV--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/1l2k2cd69mscm23srune.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In the next part of our testing journey, we will talk about the extensibility of pytest: debugging, test selection, and marking and fixtures.&lt;/p&gt;

</description>
      <category>pytest</category>
      <category>python</category>
      <category>testing</category>
      <category>unittest</category>
    </item>
    <item>
      <title>Linting Python Codes Better with Travis</title>
      <dc:creator>Edidiong Etuk</dc:creator>
      <pubDate>Thu, 14 May 2020 02:26:04 +0000</pubDate>
      <link>https://dev.to/edeediong/using-travisci-to-write-better-python-codes-27kg</link>
      <guid>https://dev.to/edeediong/using-travisci-to-write-better-python-codes-27kg</guid>
      <description>&lt;p&gt;When contributing to open source organizations, one will notice the need to follow coding standards and conventions to have your pull request reviewed and possibly merged.&lt;br&gt;
It's the same with mature companies, and a lot of startups too: they all like to follow the coding standards of their chosen programming language.&lt;br&gt;
This process is what is referred to as &lt;em&gt;linting&lt;/em&gt;. When organizations lint their codes, everybody is happy because coding standards are followed.&lt;br&gt;
But can we have this same setup in our private accounts? Can operate like these organizations in our repositories?&lt;br&gt;
The answer is yes we can and I will show you if you stick around.&lt;/p&gt;

&lt;p&gt;At the end of this tutorial we will:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;understand what linting is&lt;/li&gt;
&lt;li&gt;setup and Integrate TravisCI to our repositories&lt;/li&gt;
&lt;li&gt;use Travis CI to lint Python codes using flake8 and pylint&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;
  
  
  What is Linting
&lt;/h2&gt;

&lt;p&gt;Linting is referred to as the process of analyzing source code to flag programming errors and stylistic errors.&lt;br&gt;
Linting, when done properly, can detect formatting discrepancy, errors in your program and ensure you adhere to coding standards and conventions.&lt;br&gt;
Linters (a tool for linting) ensures you follow best practices, makes your code readable and easy to maintain and possibly save time.&lt;br&gt;
Organizations use CI tools to automate their linting and also ensure that future contributors to that codebase follow lint rules.&lt;/p&gt;

&lt;p&gt;Every language uses their own set of lines so I'd just list three linters with three programming languages below:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Python: pylint, flake8, bandit&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Golang: go-critic, go-vet, golangci-lint(this contains all the linters in Go language)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;JavaScript: ESLint, JSLint.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For the focus of this tutorial, we will focus on linting python codes.&lt;/p&gt;
&lt;h2&gt;
  
  
  Setup TravisCI and Integrate TravisCI to your repositories
&lt;/h2&gt;

&lt;p&gt;In the previous section, we talked about organizations using CI tools to automate their linting. But what is CI?&lt;/p&gt;

&lt;p&gt;Continuous integration is a software development practise where developers regularly merge their code changes into a central repository, after which automated builds and tests are run.&lt;br&gt;
Continuous integration most often refers to the build or integration stage of the software release process and entails both an automation component (e.g. a CI or build service) and a cultural component (e.g. learning to integrate frequently).&lt;br&gt;
Travis CI (c'mon it's in the name) is one of those tools used by organizations to automate their testing for lint. A lot of open source organizations use Travis for their automation and we will mimic them in automating our check for lint.&lt;/p&gt;

&lt;p&gt;Travis CI has all the required steps to set up in their documentation so it will be redundant to have to type it out here. Do check out their documentation &lt;a href="https://docs.travis-ci.com/user/tutorial/"&gt;here&lt;/a&gt;.&lt;br&gt;
Once you're done with this, Travis is all set up and linked with your account.&lt;br&gt;
To integrate Travis with your repositories, you need to add a &lt;strong&gt;.travis.yml&lt;/strong&gt; file in your project-level directory to trigger a Travis CI build.&lt;/p&gt;
&lt;h2&gt;
  
  
  Linting Python Codes with Travis CI
&lt;/h2&gt;

&lt;p&gt;Now we made mention of linters in Python earlier, so we'd pick two from there and use: flake8 and pylint. We will check the following code with the packages.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;json&lt;/span&gt;
&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Dog&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;


    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;__init__&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;age&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="s"&gt;"""Initialize name and age attributes."""&lt;/span&gt;
        &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;dog_name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt;
        &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;dog_age&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;age&lt;/span&gt;
        &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"Rambo"&lt;/span&gt;
        &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;age&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;12&lt;/span&gt;


    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;sit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="k"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;f"&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;dog_name&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt; is now sitting"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;


    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;roll_over&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="k"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;f"&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;dog_age&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt; rolled over!"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="n"&gt;my_dog&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Dog&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Maxwell"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

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



&lt;p&gt;Save the above code in a new file called &lt;code&gt;app.py&lt;/code&gt; Then we create a &lt;code&gt;requirements.txt&lt;/code&gt; file with the contents below&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;pytest-pylint==0.16.1
pytest-flake8==1.0.5
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;We choose these packages because Travis CI will need to run a test and what better package to use that pytest package.&lt;br&gt;
Pytest is used for running tests and will be expanded upon in subsequent articles.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note&lt;/strong&gt;: The following sessions should be done individually. Use the flake8 package first, watch the results and after you fix it, return your code to the format above and test with pylint.&lt;br&gt;
This is done so you see the differences between both packages and you choose the one you love the most.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3&gt;
  
  
  Flake8
&lt;/h3&gt;

&lt;p&gt;Flake8 is a tool for style guide enforcement. This means flake8's principal purpose to ensure you style your codes properly.&lt;br&gt;
It's "the wrapper which verifies pep8, pyflakes and circular complexity".&lt;br&gt;
 To set it up in Travis, create a Travis YAML file as you were told above and add the following code to it.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;language&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;python&lt;/span&gt;
&lt;span class="na"&gt;python&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;3.8"&lt;/span&gt;

&lt;span class="na"&gt;install&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;pip install -r requirements.txt&lt;/span&gt;
&lt;span class="na"&gt;scripts&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;pytest --flake8&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;&lt;p&gt;language: this tells Travis to use a python as the programming language for this build.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;python: here you choose the version you want to test your code with, it supports all python version from 2.7 to present but we're testing our codes with python version 3.8.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;install: We're installing the packages we already defined in our &lt;code&gt;requirements.txt&lt;/code&gt; file. We want to install the packages in Travis environment so it can be accessed.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;scripts: Here, we're executing the &lt;code&gt;pytest --flake8&lt;/code&gt; package we installed. This package is pytest and flake8 rolled in one. Meaning it will test all &lt;code&gt;.py&lt;/code&gt; files in the code against the flake8.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Pylint
&lt;/h3&gt;

&lt;p&gt;Pylint is a bit different from flake8, it's the full dose really: it checks style guide, programmatic errors and follows best practices.&lt;br&gt;
Some even say pylint is too strict in its rules (well it's true and you'd see it) so some people use &lt;code&gt;black&lt;/code&gt; instead of pylint.&lt;br&gt;
We'd do the same setup as above&lt;br&gt;
Edit the file &lt;code&gt;.travis.yml&lt;/code&gt; above to use pylint,&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;language&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;python&lt;/span&gt;
&lt;span class="na"&gt;python&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;3.8"&lt;/span&gt;

&lt;span class="na"&gt;install&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;pip install -r requirements.txt&lt;/span&gt;
&lt;span class="na"&gt;scripts&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;pytest --pylint&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;It follows the same explanation as to the above and this time we're executing pylint to check instead of flake8.&lt;/p&gt;

&lt;h3&gt;
  
  
  Results
&lt;/h3&gt;

&lt;p&gt;When we commit the above code to the repository, Travis builds the environment needed to test the code against either flake8 or pylint.&lt;br&gt;
If you use the flake8 package, you should get the following error:&lt;/p&gt;

&lt;p&gt;If you use the pylint package, you should get the following error:&lt;/p&gt;

&lt;p&gt;Now pylint has an annoying &lt;code&gt;C103: Constant name "my_dog" doesn't conform to UPPER_CASE naming style (invalid-name)&lt;/code&gt; rule.&lt;br&gt;
I don't like so we will choose to ignore that particular error, and we do that by ...&lt;/p&gt;

&lt;p&gt;So the final code for that passes both flake8 and pylint is as below:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="s"&gt;"""This module is an attempt to practise class in python."""&lt;/span&gt;


&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Dog&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="s"&gt;"""A simple attempt to model a dog."""&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;__init__&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;age&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="s"&gt;"""Initialize name and age attributes."""&lt;/span&gt;
        &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;dog_name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt;
        &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;dog_age&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;age&lt;/span&gt;
        &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"Rambo"&lt;/span&gt;
        &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;age&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;12&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;sit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="s"&gt;"""Simulate a dog sitting in response to a command."""&lt;/span&gt;
        &lt;span class="k"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;f"&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;dog_name&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt; is now sitting"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;roll_over&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="s"&gt;"""Simulate a dog sitting in response to a command."""&lt;/span&gt;
        &lt;span class="k"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;f"&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;dog_age&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt; rolled over!"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;


&lt;span class="n"&gt;my_dog&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Dog&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Maxwell"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

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



&lt;p&gt;Now if we push our codes to the git repository, the tests pass successfully. If you check the email linked to your git account, you should see a congratulatory message saying you've fixed the build.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;We have seen what linting is, how to add Travis CI to our git environment, and used the linters in Python to test our code against Python rules.&lt;br&gt;
You should know you can also use Travis to test if your code does what it is supposed to do. That is called Test-Driven Development and we will talk a lot about that in our upcoming Pytest series.&lt;/p&gt;

&lt;p&gt;Till then, enjoy the power of automation!&lt;/p&gt;

</description>
      <category>python</category>
      <category>pylint</category>
      <category>flake8</category>
      <category>travisci</category>
    </item>
  </channel>
</rss>
