<?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: Elena</title>
    <description>The latest articles on DEV Community by Elena (@ice_lenor).</description>
    <link>https://dev.to/ice_lenor</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%2F17692%2F0c1e08f1-cb6c-4ae7-be0b-3fd5ce00f174.jpg</url>
      <title>DEV Community: Elena</title>
      <link>https://dev.to/ice_lenor</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/ice_lenor"/>
    <language>en</language>
    <item>
      <title>Unit Testing: Mocks</title>
      <dc:creator>Elena</dc:creator>
      <pubDate>Wed, 18 Sep 2019 17:14:41 +0000</pubDate>
      <link>https://dev.to/itnext/unit-testing-mocks-59p5</link>
      <guid>https://dev.to/itnext/unit-testing-mocks-59p5</guid>
      <description>&lt;p&gt;In this tutorial we learn how to use mocks when unit testing, why integration testing is sometimes just not enough, and how to save some trees. 🌳&lt;/p&gt;

&lt;h1&gt;Prerequisites&lt;/h1&gt;

&lt;p&gt;I assume that you already are familiar with some basic concepts of unit testing. I’ll be using Java, JUnit and Mockito, but don’t worry if you’re not familiar with them: the purpose of this tutorial is to learn to use mocking. You’ll pick up platform-specific things on the fly.&lt;/p&gt;

&lt;p&gt;Here is &lt;a href="https://github.com/ice-lenor/UnitTestsMocks" rel="noopener noreferrer"&gt;a link to the repository&lt;/a&gt; where I have put the full source code for this article. You can download it and look at it while reading, or look at it afterwards.&lt;/p&gt;

&lt;p&gt;Let’s go!&lt;/p&gt;

&lt;h1&gt;Our project&lt;/h1&gt;

&lt;p&gt;I borrowed this idea from a friend. Her son, 5 years old at the time, would ask her every day: "Mommy, mommy, how many days did I live today?"&lt;/p&gt;

&lt;p&gt;The mommy would calculate and tell him: "Sweetie, you are 1868 days old today".&lt;/p&gt;

&lt;p&gt;Next day, the son would ask again.&lt;/p&gt;

&lt;p&gt;So she wrote him an iOS app that he could open every day and see for himself.&lt;/p&gt;

&lt;p&gt;I thought this could be a nice idea to base this tutorial on :).&lt;/p&gt;

&lt;p&gt;Of course, we are not going to write a full iOS app today. Our project is going to be a simple Java console app. We are going to have a small database with several registered users. When the user requests their age in days, we are going to tell them.&lt;/p&gt;

&lt;p&gt;I am going to omit a lot of functionality in our app: there is going to be no user registration process; and our database is a small &lt;code&gt;.csv&lt;/code&gt; file; and there is no fancy user interface, just a print to the console. I made this example as simple as possible to illustrate the mocking technique.&lt;/p&gt;

&lt;p&gt;Here is &lt;a href="https://github.com/ice-lenor/UnitTestsMocks" rel="noopener noreferrer"&gt;the repository&lt;/a&gt; again, where all the source code is located.&lt;/p&gt;

&lt;p&gt;Our main logic is located in this file, &lt;a href="https://github.com/ice-lenor/UnitTestsMocks/blob/master/src/main/java/user_age/UserAgeCalculator.java" rel="noopener noreferrer"&gt;UserAgeCalculator.java&lt;/a&gt;. It contains the method &lt;code&gt;calculateUserAge&lt;/code&gt; that is going to be the centre of our attention today.&lt;/p&gt;

&lt;pre&gt;
// Calculates the user age in days.
public int calculateUserAge(int userId, Date dateTo) {
    User user = usersDatabase.getUserById(userId);
    if (user == null)
        throw new IllegalArgumentException("User doesn't exist");

    double daysDateTo = dateTo.getTime() / MILLISECONDS_IN_DAY;
    double daysUserBirthDate = user.getBirthDate().getTime() / MILLISECONDS_IN_DAY;
    return (int)(daysDateTo - daysUserBirthDate);
}
&lt;/pre&gt;

&lt;p&gt;This code is pretty straightforward. First, we fetch the user from our database based on the userId. If the user wasn't found, we throw an exception, because we cannot calculate the age of someone we don't know.&lt;/p&gt;

&lt;p&gt;After that, we calculate the difference in days between the provided date and the user birth date.&lt;/p&gt;

&lt;p&gt;If we take a look at &lt;a href="https://github.com/ice-lenor/UnitTestsMocks/blob/master/resources/users_database.csv" rel="noopener noreferrer"&gt;our database&lt;/a&gt;, this is what it looks like:&lt;/p&gt;

&lt;pre&gt;
1,"Emma","1983-12-03"
2,"Janneke","1992-04-25"
3,"Jaap","1996-02-19"
4,"Sophie","1978-07-30"
5,"Pieter","2019-01-01"
&lt;/pre&gt;

&lt;p&gt;We have several users registered, all with the user id, their name, and their birth date.&lt;/p&gt;

&lt;p&gt;And now, to our first test.&lt;/p&gt;

&lt;h1&gt;First test&lt;/h1&gt;

&lt;p&gt;Here is &lt;a href="https://github.com/ice-lenor/UnitTestsMocks/blob/master/src/test/java/user_age/UserAgeCalculatorTest1.java" rel="noopener noreferrer"&gt;our first test&lt;/a&gt;.&lt;/p&gt;

&lt;pre&gt;
&lt;a class="mentioned-user" href="https://dev.to/test"&gt;@test&lt;/a&gt;
public void userEmmaAge() {
    UsersDatabase usersDatabase = new UsersDatabase();
    UserAgeCalculator calculator = new UserAgeCalculator(usersDatabase);
    Date dateTo = DateHelpers.parseDate("2019-01-01");

    int resultAge = calculator.calculateUserAge(1, dateTo);

    assertEquals(12813, resultAge);
}
&lt;/pre&gt;

&lt;p&gt;We have picked the user with id=1, who is called Emma, and have calculated the difference in days between the 1st of January 2019 and Emma's birthday, which is the 3rd of December 1983.&lt;/p&gt;

&lt;p&gt;Emma is 12813 days old.&lt;/p&gt;

&lt;h2&gt;Integration test?&lt;/h2&gt;

&lt;p&gt;What we have just written is called an integration test.&lt;/p&gt;

&lt;p&gt;We are not only testing our &lt;code&gt;calculateUserAge&lt;/code&gt; method. We are testing several pieces of code together. In other words, our &lt;code&gt;calculateUserAge&lt;/code&gt; &lt;em&gt;depends&lt;/em&gt; on other code in order to work, and we have kept this dependency in our tests.&lt;/p&gt;

&lt;p&gt;What does it depend on?&lt;/p&gt;

&lt;p&gt;Actually, it depends on the implementation of the &lt;code&gt;UsersDatabase&lt;/code&gt;. &lt;code&gt;calculateUserAge&lt;/code&gt; is calling the &lt;code&gt;UsersDatabase.getUserById&lt;/code&gt; method, which opens the database, reads the user by id, and returns this user to the caller.&lt;/p&gt;

&lt;p&gt;So, in short, our unit test has a dependency on the database.&lt;/p&gt;

&lt;h2&gt;Why is this bad?&lt;/h2&gt;

&lt;p&gt;This is not necessarily bad.&lt;/p&gt;

&lt;p&gt;Integration tests are a great tool to ensure that your whole app is working well together. When you have several pieces of code, covered well with unit tests, but you haven't tested them working together, there is a chance that you missed a bug. There might be a problem with the pieces working together, and you might miss it if you only test them individually.&lt;/p&gt;

&lt;p&gt;If we were working on a real app here, we could decide to have a bunch of unit tests for checking the calculation logic and a couple of integration tests to ensure that the whole app works well.&lt;/p&gt;

&lt;p&gt;Integration tests are usually more expensive to run. When your test accesses a database, pushes some data into a queue, calls another service via network and processes the response data, this takes time. An integration test will run slower than a unit test.&lt;/p&gt;

&lt;p&gt;Along with that, you might need some protection measures to ensure your integration test doesn't mess with the real production data.&lt;/p&gt;

&lt;h2&gt;Why is using the production data bad?&lt;/h2&gt;

&lt;p&gt;Again, it is not necessarily bad in itself. However, there are some complexities this adds.&lt;/p&gt;

&lt;h3&gt;Tests writing in the database&lt;/h3&gt;

&lt;p&gt;One problem occurs if your test writes some data to a database. If you run this test, there will be new entries in the database. You will have to take measures to ensure you don't run this on the production database.&lt;/p&gt;

&lt;h3&gt;Tests reading from the database&lt;/h3&gt;

&lt;p&gt;It is a bit easier with reading the data. When reading the data, you don't mess with it, you just read it, right? Your production stays safe, right?&lt;/p&gt;

&lt;p&gt;While this might be true, there are some problems with reading still.&lt;/p&gt;

&lt;h2&gt;Missing cases&lt;/h2&gt;

&lt;p&gt;We can list a couple of problems with integration tests that will not let us test our app fully and extensively.&lt;/p&gt;

&lt;h3&gt;Data stability&lt;/h3&gt;

&lt;p&gt;One problem is that production data is sometimes &lt;strong&gt;not stable&lt;/strong&gt;. In our age-calculating app, new users are registered every day, and some users leave the app as well.&lt;/p&gt;

&lt;p&gt;What happens if Emma deletes her account?&lt;/p&gt;

&lt;p&gt;You can simulate that by deleting Emma from &lt;a href="https://github.com/ice-lenor/UnitTestsMocks/blob/master/resources/users_database.csv" rel="noopener noreferrer"&gt;our little database&lt;/a&gt; and running the test.&lt;/p&gt;

&lt;p&gt;Yes, our test will start failing. Since the user with id=1 will not be found, the &lt;code&gt;calculateUserAge&lt;/code&gt; method will throw an exception, and this is definitely not what we expect.&lt;/p&gt;

&lt;h3&gt;Data richness&lt;/h3&gt;

&lt;p&gt;The production data for our new app is small. Many cases are not present in our database (just yet).&lt;/p&gt;

&lt;p&gt;If we think about cases, like we discussed &lt;a href="http://smartpuffin.com/unit-tests-tutorial/" rel="noopener noreferrer"&gt;in this article&lt;/a&gt;, we might find that we want to test much more than just our 5 users offer.&lt;/p&gt;

&lt;p&gt;For example, right now we don't have a user who is going to be born in the future. But it is possible that an expecting parent might register in our app and count the days before the baby arrives, according to the doctors' predictions. I would like to test this case just to make sure that when this happens in production, our app is prepared and displays the correct number: i.e., -10 days.&lt;/p&gt;

&lt;p&gt;Another case would be when we want to calculate the age of a user not present in the database. Remember, our &lt;code&gt;calculateUserAge&lt;/code&gt; method throws an exception in this case.&lt;/p&gt;

&lt;p&gt;For this, we need to fetch a user in the test whose id is not present in the database. say, we have 5 users right now, with ids from 1 to 5, how about we use 42 for a non-existing user?&lt;/p&gt;

&lt;pre&gt;
&lt;a class="mentioned-user" href="https://dev.to/test"&gt;@test&lt;/a&gt;
public void nonExistingUser() {
    UsersDatabase usersDatabase = new UsersDatabase();
    UserAgeCalculator calculator = new UserAgeCalculator(usersDatabase);

    Date dateTo = DateHelpers.parseDate("2019-09-12");

    assertThrows(IllegalArgumentException.class, () -&amp;gt; {
        int resultAge = calculator.calculateUserAge(42, dateTo);
    });
}
&lt;/pre&gt;

&lt;p&gt;Of course, if our app is popular, we'll reach 42 users in no time. This test will start to fail because it won't be throwing an exception anymore.&lt;/p&gt;

&lt;h3&gt;Environment stability&lt;/h3&gt;

&lt;p&gt;When the connection to our database fails, we might want to display a message to the user: "Sorry, something went wrong, please try again in a moment".&lt;/p&gt;

&lt;p&gt;Naturally, we might want to test that.&lt;/p&gt;

&lt;p&gt;However, it might just so happen that our connection is rather stable, and the database doesn't go down while you're running your tests.&lt;/p&gt;

&lt;p&gt;This means that a test expecting the database to fail will most likely never pass.&lt;/p&gt;

&lt;p&gt;Imagine a different app that compiles a report and sends it to a printer. You wouldn't want to waste paper every time you want to run the tests, would you? In cases like this one, "cutting off" the real environment helps to simplify the app and concentrate on its logic, and also save some trees. 🌳&lt;/p&gt;

&lt;h1&gt;Mocking&lt;/h1&gt;

&lt;p&gt;In order to overcome these problems, we will turn this test into a true unit test. We will cut off the dependency on the database and will replace it with our own "database", a fake one, the one that we will make individually for each test.&lt;/p&gt;

&lt;p&gt;The code will not know the database is fake and will work as it should. But we will! And this makes us powerful.&lt;/p&gt;

&lt;p&gt;Let us see how it's done.&lt;/p&gt;

&lt;p&gt;Take a look at this &lt;a href="https://github.com/ice-lenor/UnitTestsMocks/blob/master/src/test/java/user_age/UserAgeCalculatorTest2.java" rel="noopener noreferrer"&gt;new test suite&lt;/a&gt;.&lt;/p&gt;

&lt;pre&gt;
&lt;a class="mentioned-user" href="https://dev.to/test"&gt;@test&lt;/a&gt;
public void userBabyAge() {
    UsersDatabase usersDatabase = Mockito.mock(UsersDatabase.class);
    int userId = 42;
    User user = new User(userId, "Baby", DateHelpers.parseDate("2019-09-01"));
    Mockito.when(usersDatabase.getUserById(userId)).thenReturn(user);

    Date dateTo = DateHelpers.parseDate("2019-09-12");

    UserAgeCalculator calculator = new UserAgeCalculator(usersDatabase);

    int resultAge = calculator.calculateUserAge(userId, dateTo);

    assertEquals(11, resultAge);
}
&lt;/pre&gt;

&lt;p&gt;Look at how we create the &lt;code&gt;UsersDatabase&lt;/code&gt; instance. Here is what we did before:&lt;/p&gt;

&lt;pre&gt;
UsersDatabase usersDatabase = new UsersDatabase();
&lt;/pre&gt;

&lt;p&gt;And here's what we are doing now:&lt;/p&gt;

&lt;pre&gt;
UsersDatabase usersDatabase = Mockito.mock(UsersDatabase.class);
&lt;/pre&gt;

&lt;p&gt;We have just created a pretend database, a completely fake one, which will behave as we wish, and will only exist for our test.&lt;/p&gt;

&lt;p&gt;After that, we create a user:&lt;/p&gt;

&lt;pre&gt;
User user = new User(userId, "Baby", DateHelpers.parseDate("2019-09-01"));
&lt;/pre&gt;

&lt;p&gt;We have just created a user which does not exist in our database. A completely pretend user, not real.&lt;/p&gt;

&lt;p&gt;Then, we make our pretend database work with our fake user:&lt;/p&gt;

&lt;pre&gt;
Mockito.when(usersDatabase.getUserById(userId)).thenReturn(user);
&lt;/pre&gt;

&lt;p&gt;After that, we create our calculator and calculate the age of this very user with &lt;code&gt;userId = 42&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;See what we're doing here? Only this imaginary user "exists" in our pretend "database", and we made them only for this test. The test doesn't access the real &lt;code&gt;UsersDatabase&lt;/code&gt; now. We have all the power!&lt;/p&gt;

&lt;p&gt;This technique is called &lt;em&gt;mocking&lt;/em&gt;, and this fake database is called a &lt;em&gt;mock&lt;/em&gt;. By adding this mock and replacing the real database with it, we have made our test a pure unit test. This is really powerful because now we can test all scenarios that we couldn't before.&lt;/p&gt;

&lt;p&gt;How about a non-existing user? How about a user from the future? Everything is possible now.&lt;/p&gt;

&lt;h2&gt;What are other things mocks are useful for?&lt;/h2&gt;

&lt;p&gt;Imagine we would not return the age of the user as a return value, but instead would print it on paper.&lt;/p&gt;

&lt;p&gt;This would be very difficult to test. Of course, you don't want to waste paper, but the larger problem is that your test would have to find the printer, pull the paper out of it, photograph the text, apply some cool text recognition techniques to see what is being printed, and compare the recognised text with the expected value.&lt;/p&gt;

&lt;p&gt;This sounds pretty cool, but it is so difficult to implement. Is there a way to do it easier?&lt;/p&gt;

&lt;p&gt;Yes, mocking helps with this as well. If you would mock the printer instance, you could ensure that &lt;code&gt;Printer.print()&lt;/code&gt; was called exactly once with specific arguments.&lt;/p&gt;

&lt;p&gt;Mocking frameworks have a number of useful possibilities. You can &lt;a href="https://github.com/ice-lenor/UnitTestsMocks/blob/master/src/test/java/user_age/MockingCapabilities.java" rel="noopener noreferrer"&gt;check how many times a method was called&lt;/a&gt;. You can see what arguments were passed each time and then compare only the ones that are needed. You can mock several consecutive calls to one method and make them return different values. You can make every second call throw an exception. I am not sure if this would be useful, but hey, it might be. Take a look at the documentation of your favourite mocking framework to see the full list.&lt;/p&gt;

&lt;h2&gt;Summary&lt;/h2&gt;

&lt;p&gt;We have briefly discussed the difference between unit tests and integration tests. Sometimes, unit tests are more desirable than integration tests. Along with that, writing, supporting and running unit tests is easier and cheaper than integration tests.&lt;/p&gt;

&lt;p&gt;We have learned to apply mocking in order to isolate our code from external dependencies and write pure unit tests.&lt;/p&gt;

&lt;p&gt;Mocking lets us explore more scenarios that were not possible when using "real" data, and our tests are more stable because we control the environment now.&lt;/p&gt;

</description>
      <category>unittesting</category>
      <category>codequality</category>
      <category>testing</category>
    </item>
    <item>
      <title>Unit Testing: Mocks</title>
      <dc:creator>Elena</dc:creator>
      <pubDate>Thu, 12 Sep 2019 14:32:48 +0000</pubDate>
      <link>https://dev.to/ice_lenor/unit-testing-mocks-2ki3</link>
      <guid>https://dev.to/ice_lenor/unit-testing-mocks-2ki3</guid>
      <description>&lt;p&gt;This post was originally published in my blog &lt;a href="https://smartpuffin.com/unit-tests-mocks/" rel="noopener noreferrer"&gt;smartpuffin.com&lt;/a&gt;.&lt;/p&gt;




&lt;p&gt;In this tutorial we learn how to use mocks when unit testing, why integration testing is sometimes just not enough, and how to save some trees. 🌳&lt;/p&gt;

&lt;h1&gt;Prerequisites&lt;/h1&gt;

&lt;p&gt;I assume that you already are familiar with some basic concepts of unit testing. I’ll be using Java, JUnit and Mockito, but don’t worry if you’re not familiar with them: the purpose of this tutorial is to learn to use mocking. You’ll pick up platform-specific things on the fly.&lt;/p&gt;

&lt;p&gt;Here is &lt;a href="https://github.com/ice-lenor/UnitTestsMocks" rel="noopener noreferrer"&gt;a link to the repository&lt;/a&gt; where I have put the full source code for this article. You can download it and look at it while reading, or look at it afterwards.&lt;/p&gt;

&lt;p&gt;Let’s go!&lt;/p&gt;

&lt;h1&gt;Our project&lt;/h1&gt;

&lt;p&gt;I borrowed this idea from a friend. Her son, 5 years old at the time, would ask her every day: "Mommy, mommy, how many days did I live today?"&lt;/p&gt;

&lt;p&gt;The mommy would calculate and tell him: "Sweetie, you are 1868 days old today".&lt;/p&gt;

&lt;p&gt;Next day, the son would ask again.&lt;/p&gt;

&lt;p&gt;So she wrote him an iOS app that he could open every day and see for himself.&lt;/p&gt;

&lt;p&gt;I thought this could be a nice idea to base this tutorial on :).&lt;/p&gt;

&lt;p&gt;Of course, we are not going to write a full iOS app today. Our project is going to be a simple Java console app. We are going to have a small database with several registered users. When the user requests their age in days, we are going to tell them.&lt;/p&gt;

&lt;p&gt;I am going to omit a lot of functionality in our app: there is going to be no user registration process; and our database is a small &lt;code&gt;.csv&lt;/code&gt; file; and there is no fancy user interface, just a print to the console. I made this example as simple as possible to illustrate the mocking technique.&lt;/p&gt;

&lt;p&gt;Here is &lt;a href="https://github.com/ice-lenor/UnitTestsMocks" rel="noopener noreferrer"&gt;the repository&lt;/a&gt; again, where all the source code is located.&lt;/p&gt;

&lt;p&gt;Our main logic is located in this file, &lt;a href="https://github.com/ice-lenor/UnitTestsMocks/blob/master/src/main/java/user_age/UserAgeCalculator.java" rel="noopener noreferrer"&gt;UserAgeCalculator.java&lt;/a&gt;. It contains the method &lt;code&gt;calculateUserAge&lt;/code&gt; that is going to be the centre of our attention today.&lt;/p&gt;

&lt;pre&gt;
// Calculates the user age in days.
public int calculateUserAge(int userId, Date dateTo) {
    User user = usersDatabase.getUserById(userId);
    if (user == null)
        throw new IllegalArgumentException("User doesn't exist");

    double daysDateTo = dateTo.getTime() / MILLISECONDS_IN_DAY;
    double daysUserBirthDate = user.getBirthDate().getTime() / MILLISECONDS_IN_DAY;
    return (int)(daysDateTo - daysUserBirthDate);
}
&lt;/pre&gt;

&lt;p&gt;This code is pretty straightforward. First, we fetch the user from our database based on the userId. If the user wasn't found, we throw an exception, because we cannot calculate the age of someone we don't know.&lt;/p&gt;

&lt;p&gt;After that, we calculate the difference in days between the provided date and the user birth date.&lt;/p&gt;

&lt;p&gt;If we take a look at &lt;a href="https://github.com/ice-lenor/UnitTestsMocks/blob/master/resources/users_database.csv" rel="noopener noreferrer"&gt;our database&lt;/a&gt;, this is what it looks like:&lt;/p&gt;

&lt;pre&gt;
1,"Emma","1983-12-03"
2,"Janneke","1992-04-25"
3,"Jaap","1996-02-19"
4,"Sophie","1978-07-30"
5,"Pieter","2019-01-01"
&lt;/pre&gt;

&lt;p&gt;We have several users registered, all with the user id, their name, and their birth date.&lt;/p&gt;

&lt;p&gt;And now, to our first test.&lt;/p&gt;

&lt;h1&gt;First test&lt;/h1&gt;

&lt;p&gt;Here is &lt;a href="https://github.com/ice-lenor/UnitTestsMocks/blob/master/src/test/java/user_age/UserAgeCalculatorTest1.java" rel="noopener noreferrer"&gt;our first test&lt;/a&gt;.&lt;/p&gt;

&lt;pre&gt;
&lt;a class="mentioned-user" href="https://dev.to/test"&gt;@test&lt;/a&gt;
public void userEmmaAge() {
    UsersDatabase usersDatabase = new UsersDatabase();
    UserAgeCalculator calculator = new UserAgeCalculator(usersDatabase);
    Date dateTo = DateHelpers.parseDate("2019-01-01");

    int resultAge = calculator.calculateUserAge(1, dateTo);

    assertEquals(12813, resultAge);
}
&lt;/pre&gt;

&lt;p&gt;We have picked the user with id=1, who is called Emma, and have calculated the difference in days between the 1st of January 2019 and Emma's birthday, which is the 3rd of December 1983.&lt;/p&gt;

&lt;p&gt;Emma is 12813 days old.&lt;/p&gt;

&lt;h2&gt;Integration test?&lt;/h2&gt;

&lt;p&gt;What we have just written is called an integration test.&lt;/p&gt;

&lt;p&gt;We are not only testing our &lt;code&gt;calculateUserAge&lt;/code&gt; method. We are testing several pieces of code together. In other words, our &lt;code&gt;calculateUserAge&lt;/code&gt; &lt;em&gt;depends&lt;/em&gt; on other code in order to work, and we have kept this dependency in our tests.&lt;/p&gt;

&lt;p&gt;What does it depend on?&lt;/p&gt;

&lt;p&gt;Actually, it depends on the implementation of the &lt;code&gt;UsersDatabase&lt;/code&gt;. &lt;code&gt;calculateUserAge&lt;/code&gt; is calling the &lt;code&gt;UsersDatabase.getUserById&lt;/code&gt; method, which opens the database, reads the user by id, and returns this user to the caller.&lt;/p&gt;

&lt;p&gt;So, in short, our unit test has a dependency on the database.&lt;/p&gt;

&lt;h2&gt;Why is this bad?&lt;/h2&gt;

&lt;p&gt;This is not necessarily bad.&lt;/p&gt;

&lt;p&gt;Integration tests are a great tool to ensure that your whole app is working well together. When you have several pieces of code, covered well with unit tests, but you haven't tested them working together, there is a chance that you missed a bug. There might be a problem with the pieces working together, and you might miss it if you only test them individually.&lt;/p&gt;

&lt;p&gt;If we were working on a real app here, we could decide to have a bunch of unit tests for checking the calculation logic and a couple of integration tests to ensure that the whole app works well.&lt;/p&gt;

&lt;p&gt;Integration tests are usually more expensive to run. When your test accesses a database, pushes some data into a queue, calls another service via network and processes the response data, this takes time. An integration test will run slower than a unit test.&lt;/p&gt;

&lt;p&gt;Along with that, you might need some protection measures to ensure your integration test doesn't mess with the real production data.&lt;/p&gt;

&lt;h2&gt;Why is using the production data bad?&lt;/h2&gt;

&lt;p&gt;Again, it is not necessarily bad in itself. However, there are some complexities this adds.&lt;/p&gt;

&lt;h3&gt;Tests writing in the database&lt;/h3&gt;

&lt;p&gt;One problem occurs if your test writes some data to a database. If you run this test, there will be new entries in the database. You will have to take measures to ensure you don't run this on the production database.&lt;/p&gt;

&lt;h3&gt;Tests reading from the database&lt;/h3&gt;

&lt;p&gt;It is a bit easier with reading the data. When reading the data, you don't mess with it, you just read it, right? Your production stays safe, right?&lt;/p&gt;

&lt;p&gt;While this might be true, there are some problems with reading still.&lt;/p&gt;

&lt;h2&gt;Missing cases&lt;/h2&gt;

&lt;p&gt;We can list a couple of problems with integration tests that will not let us test our app fully and extensively.&lt;/p&gt;

&lt;h3&gt;Data stability&lt;/h3&gt;

&lt;p&gt;One problem is that production data is sometimes &lt;strong&gt;not stable&lt;/strong&gt;. In our age-calculating app, new users are registered every day, and some users leave the app as well.&lt;/p&gt;

&lt;p&gt;What happens if Emma deletes her account?&lt;/p&gt;

&lt;p&gt;You can simulate that by deleting Emma from &lt;a href="https://github.com/ice-lenor/UnitTestsMocks/blob/master/resources/users_database.csv" rel="noopener noreferrer"&gt;our little database&lt;/a&gt; and running the test.&lt;/p&gt;

&lt;p&gt;Yes, our test will start failing. Since the user with id=1 will not be found, the &lt;code&gt;calculateUserAge&lt;/code&gt; method will throw an exception, and this is definitely not what we expect.&lt;/p&gt;

&lt;h3&gt;Data richness&lt;/h3&gt;

&lt;p&gt;The production data for our new app is small. Many cases are not present in our database (just yet).&lt;/p&gt;

&lt;p&gt;If we think about cases, like we discussed &lt;a href="http://smartpuffin.com/unit-tests-tutorial/" rel="noopener noreferrer"&gt;in this article&lt;/a&gt;, we might find that we want to test much more than just our 5 users offer.&lt;/p&gt;

&lt;p&gt;For example, right now we don't have a user who is going to be born in the future. But it is possible that an expecting parent might register in our app and count the days before the baby arrives, according to the doctors' predictions. I would like to test this case just to make sure that when this happens in production, our app is prepared and displays the correct number: i.e., -10 days.&lt;/p&gt;

&lt;p&gt;Another case would be when we want to calculate the age of a user not present in the database. Remember, our &lt;code&gt;calculateUserAge&lt;/code&gt; method throws an exception in this case.&lt;/p&gt;

&lt;p&gt;For this, we need to fetch a user in the test whose id is not present in the database. say, we have 5 users right now, with ids from 1 to 5, how about we use 42 for a non-existing user?&lt;/p&gt;

&lt;pre&gt;
&lt;a class="mentioned-user" href="https://dev.to/test"&gt;@test&lt;/a&gt;
public void nonExistingUser() {
    UsersDatabase usersDatabase = new UsersDatabase();
    UserAgeCalculator calculator = new UserAgeCalculator(usersDatabase);

    Date dateTo = DateHelpers.parseDate("2019-09-12");

    assertThrows(IllegalArgumentException.class, () -&amp;gt; {
        int resultAge = calculator.calculateUserAge(42, dateTo);
    });
}
&lt;/pre&gt;

&lt;p&gt;Of course, if our app is popular, we'll reach 42 users in no time. This test will start to fail because it won't be throwing an exception anymore.&lt;/p&gt;

&lt;h3&gt;Environment stability&lt;/h3&gt;

&lt;p&gt;When the connection to our database fails, we might want to display a message to the user: "Sorry, something went wrong, please try again in a moment".&lt;/p&gt;

&lt;p&gt;Naturally, we might want to test that.&lt;/p&gt;

&lt;p&gt;However, it might just so happen that our connection is rather stable, and the database doesn't go down while you're running your tests.&lt;/p&gt;

&lt;p&gt;This means that a test expecting the database to fail will most likely never pass.&lt;/p&gt;

&lt;p&gt;Imagine a different app that compiles a report and sends it to a printer. You wouldn't want to waste paper every time you want to run the tests, would you? In cases like this one, "cutting off" the real environment helps to simplify the app and concentrate on its logic, and also save some trees. 🌳&lt;/p&gt;

&lt;h1&gt;Mocking&lt;/h1&gt;

&lt;p&gt;In order to overcome these problems, we will turn this test into a true unit test. We will cut off the dependency on the database and will replace it with our own "database", a fake one, the one that we will make individually for each test.&lt;/p&gt;

&lt;p&gt;The code will not know the database is fake and will work as it should. But we will! And this makes us powerful.&lt;/p&gt;

&lt;p&gt;Let us see how it's done.&lt;/p&gt;

&lt;p&gt;Take a look at this &lt;a href="https://github.com/ice-lenor/UnitTestsMocks/blob/master/src/test/java/user_age/UserAgeCalculatorTest2.java" rel="noopener noreferrer"&gt;new test suite&lt;/a&gt;.&lt;/p&gt;

&lt;pre&gt;
&lt;a class="mentioned-user" href="https://dev.to/test"&gt;@test&lt;/a&gt;
public void userBabyAge() {
    UsersDatabase usersDatabase = Mockito.mock(UsersDatabase.class);
    int userId = 42;
    User user = new User(userId, "Baby", DateHelpers.parseDate("2019-09-01"));
    Mockito.when(usersDatabase.getUserById(userId)).thenReturn(user);

    Date dateTo = DateHelpers.parseDate("2019-09-12");

    UserAgeCalculator calculator = new UserAgeCalculator(usersDatabase);

    int resultAge = calculator.calculateUserAge(userId, dateTo);

    assertEquals(11, resultAge);
}
&lt;/pre&gt;

&lt;p&gt;Look at how we create the &lt;code&gt;UsersDatabase&lt;/code&gt; instance. Here is what we did before:&lt;/p&gt;

&lt;pre&gt;
UsersDatabase usersDatabase = new UsersDatabase();
&lt;/pre&gt;

&lt;p&gt;And here's what we are doing now:&lt;/p&gt;

&lt;pre&gt;
UsersDatabase usersDatabase = Mockito.mock(UsersDatabase.class);
&lt;/pre&gt;

&lt;p&gt;We have just created a pretend database, a completely fake one, which will behave as we wish, and will only exist for our test.&lt;/p&gt;

&lt;p&gt;After that, we create a user:&lt;/p&gt;

&lt;pre&gt;
User user = new User(userId, "Baby", DateHelpers.parseDate("2019-09-01"));
&lt;/pre&gt;

&lt;p&gt;We have just created a user which does not exist in our database. A completely pretend user, not real.&lt;/p&gt;

&lt;p&gt;Then, we make our pretend database work with our fake user:&lt;/p&gt;

&lt;pre&gt;
Mockito.when(usersDatabase.getUserById(userId)).thenReturn(user);
&lt;/pre&gt;

&lt;p&gt;After that, we create our calculator and calculate the age of this very user with &lt;code&gt;userId = 42&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;See what we're doing here? Only this imaginary user "exists" in our pretend "database", and we made them only for this test. The test doesn't access the real &lt;code&gt;UsersDatabase&lt;/code&gt; now. We have all the power!&lt;/p&gt;

&lt;p&gt;This technique is called &lt;em&gt;mocking&lt;/em&gt;, and this fake database is called a &lt;em&gt;mock&lt;/em&gt;. By adding this mock and replacing the real database with it, we have made our test a pure unit test. This is really powerful because now we can test all scenarios that we couldn't before.&lt;/p&gt;

&lt;p&gt;How about a non-existing user? How about a user from the future? Everything is possible now.&lt;/p&gt;

&lt;h2&gt;What are other things mocks are useful for?&lt;/h2&gt;

&lt;p&gt;Imagine we would not return the age of the user as a return value, but instead would print it on paper.&lt;/p&gt;

&lt;p&gt;This would be very difficult to test. Of course, you don't want to waste paper, but the larger problem is that your test would have to find the printer, pull the paper out of it, photograph the text, apply some cool text recognition techniques to see what is being printed, and compare the recognised text with the expected value.&lt;/p&gt;

&lt;p&gt;This sounds pretty cool, but it is so difficult to implement. Is there a way to do it easier?&lt;/p&gt;

&lt;p&gt;Yes, mocking helps with this as well. If you would mock the printer instance, you could ensure that &lt;code&gt;Printer.print()&lt;/code&gt; was called exactly once with specific arguments.&lt;/p&gt;

&lt;p&gt;Mocking frameworks have a number of useful possibilities. You can &lt;a href="https://github.com/ice-lenor/UnitTestsMocks/blob/master/src/test/java/user_age/MockingCapabilities.java" rel="noopener noreferrer"&gt;check how many times a method was called&lt;/a&gt;. You can see what arguments were passed each time and then compare only the ones that are needed. You can mock several consecutive calls to one method and make them return different values. You can make every second call throw an exception. I am not sure if this would be useful, but hey, it might be. Take a look at the documentation of your favourite mocking framework to see the full list.&lt;/p&gt;

&lt;h2&gt;Summary&lt;/h2&gt;

&lt;p&gt;We have briefly discussed the difference between unit tests and integration tests. Sometimes, unit tests are more desirable than integration tests. Along with that, writing, supporting and running unit tests is easier and cheaper than integration tests.&lt;/p&gt;

&lt;p&gt;We have learned to apply mocking in order to isolate our code from external dependencies and write pure unit tests.&lt;/p&gt;

&lt;p&gt;Mocking lets us explore more scenarios that were not possible when using "real" data, and our tests are more stable because we control the environment now.&lt;/p&gt;

</description>
      <category>unittesting</category>
      <category>codequality</category>
      <category>testing</category>
    </item>
    <item>
      <title>Writing Good Unit Tests: A Step By Step Tutorial</title>
      <dc:creator>Elena</dc:creator>
      <pubDate>Wed, 11 Sep 2019 16:52:38 +0000</pubDate>
      <link>https://dev.to/itnext/writing-good-unit-tests-a-step-by-step-tutorial-1l4f</link>
      <guid>https://dev.to/itnext/writing-good-unit-tests-a-step-by-step-tutorial-1l4f</guid>
      <description>&lt;p&gt;This post was originally published in my blog &lt;a href="http://smartpuffin.com/unit-tests-tutorial/" rel="noopener noreferrer"&gt;smartpuffin.com&lt;/a&gt;.&lt;/p&gt;




&lt;p&gt;Let's imagine we just wrote a method calculating distance between two points on our planet. And let's imagine we want to test it as well as possible. How do we come up with test cases? And what exactly do we need to test?&lt;/p&gt;

&lt;p&gt;Bonus: learn a surprising fact about the Fiji islands. 🇫🇯&lt;/p&gt;

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

&lt;p&gt;I assume you are already familiar with the concepts of unit testing. I'll be using Java and JUnit, but don't worry if you're not familiar with them: the purpose of this tutorial is to learn to write fuller test suites. You'll pick up platform-specific things on the fly.&lt;/p&gt;

&lt;p&gt;Here is a link &lt;a href="https://github.com/ice-lenor/ExampleUnitTests" rel="noopener noreferrer"&gt;to the repository&lt;/a&gt; where I have put the full source code for this post. You can download it and look at it while reading, or look at it afterwards.&lt;/p&gt;

&lt;p&gt;And here is my previous article on unit testing topic explaining &lt;a href="https://dev.to/ice_lenor/unit-testing-best-practices-27ec"&gt;best practices in unit testing&lt;/a&gt; more widely.&lt;/p&gt;

&lt;p&gt;Let's go!&lt;/p&gt;

&lt;h1&gt;Positive cases&lt;/h1&gt;

&lt;p&gt;Let's start with thinking about our method as of a black box.&lt;/p&gt;

&lt;p&gt;We have this API:&lt;/p&gt;

&lt;pre&gt;
// Returns distance in meters using haversine formula
double getDistance(double latitude1, double longitude1, double latitude2, double longitude2);
&lt;/pre&gt;

&lt;p&gt;What can we test?&lt;/p&gt;

&lt;h2&gt;Putting yourself in a testing mindset&lt;/h2&gt;

&lt;p&gt;You need to switch from being a developer to being a tester now. This means you have to stop trusting yourself. You can't know your code is working if you didn't test it!&lt;/p&gt;

&lt;p&gt;If you tested it manually, you don't know if it's going to work next time someone makes a change - in your code or close to it.&lt;/p&gt;

&lt;p&gt;Moreover, you can be sure that whatever code you build on top of this well-tested piece, you have one less problem to worry about.&lt;/p&gt;

&lt;p&gt;The feeling of security you have when your code is well-tested is incredible. You can refactor freely and develop new features further - and be sure your old code is not going to break.&lt;/p&gt;

&lt;p&gt;Promise yourself a treat if you find a bug. But do be careful: too many cookies are bad for your health.&lt;/p&gt;

&lt;h2&gt;First test&lt;/h2&gt;

&lt;p&gt;Okay, we are ready to test! What should we test first?&lt;/p&gt;

&lt;p&gt;The very first thing that comes to mind, is:&lt;/p&gt;

&lt;blockquote&gt;Calculate the distance between two points and compare with the true real number calculated manually. If they match, all is well!&lt;/blockquote&gt;

&lt;p&gt;And this is a great testing strategy. Let's write some tests for that.&lt;/p&gt;

&lt;p&gt;I'll pick a couple of points: one in the very north of the Netherlands, one - in the very south. Practically, I want to measure the country from top to bottom.&lt;/p&gt;

&lt;p&gt;I clicked at a couple of points on the map and got this:&lt;/p&gt;

&lt;pre&gt;Point 1: latitude = 53.478612, longitude = 6.250578.
Point 2: latitude = 50.752342, longitude = 5.916981.
&lt;/pre&gt;

&lt;p&gt;I have used an external website to calculate the distance and got 304001.021046 meters. That means the Netherlands are 304km long!&lt;/p&gt;

&lt;p&gt;Now, how do we use this?&lt;/p&gt;

&lt;h2&gt;Thinking about domain area&lt;/h2&gt;

&lt;p&gt;We need to think about domain area-specific things. Not all of them are obvious from the code: some of them depend on the area, some - on the future plans.&lt;/p&gt;

&lt;p&gt;In our example, the returned distance is in meters, and it's a double.&lt;/p&gt;

&lt;p&gt;We know that a double is prone to rounding errors. Moreover, we know that the method used in this calculation - the haversine formula - is somewhat imprecise for our oh-so-complex planet. It is enough for our application now, but perhaps, we'll want to replace it with higher-precision calculation.&lt;/p&gt;

&lt;p&gt;All this makes us think that we should compare our calculated value with our expected value with some precision.&lt;/p&gt;

&lt;p&gt;Let's pick some value that is good for our domain area. To do that, we can remember about our domain area and requirements again. Would 1mm be fine? Probably it would.&lt;/p&gt;

&lt;p&gt;And here is our first test!&lt;/p&gt;

&lt;pre&gt;double Precision = 0.001; // We are comparing calculated distance using 1mm precision
...
&lt;a class="mentioned-user" href="https://dev.to/test"&gt;@test&lt;/a&gt;
void distanceTheNetherlandsNorthToSouth() {
    double distance = GeometryHelpers.getDistance(53.478612, 6.250578, 50.752342, 5.916981);
    assertEquals(304001.0210, distance, Precision);
}
&lt;/pre&gt;

&lt;p&gt;Let's run this test and make sure it passes. Yay!&lt;/p&gt;

&lt;h2&gt;More tests&lt;/h2&gt;

&lt;p&gt;We calculated the distance across the Netherlands. But of course, it is a nice idea to double-check and to triple-check.&lt;/p&gt;

&lt;p&gt;Your tests should vary - this helps you cast a wider net for these pesky bugs!&lt;/p&gt;

&lt;p&gt;Let's find some more nice points. How about we learn how wide Australia is?&lt;/p&gt;

&lt;pre&gt;&lt;a class="mentioned-user" href="https://dev.to/test"&gt;@test&lt;/a&gt;
void distanceAustraliaWestToEast() {
    double distance = GeometryHelpers.getDistance(-23.939607, 113.585605, -28.293166, 153.718989);
    assertEquals(4018083.0398, distance, Precision);
}&lt;/pre&gt;
Or how far is it from Capetown to Johannesburg?
&lt;pre&gt;&lt;a class="mentioned-user" href="https://dev.to/test"&gt;@test&lt;/a&gt;
void distanceFromCapetownToJohannesburg() {
    double distance = GeometryHelpers.getDistance(-33.926510, 18.364603,-26.208450, 28.040572);
    assertEquals(1265065.6094, distance, Precision);
}&lt;/pre&gt;
Now that we think about that: are we sure that the distance doesn't depend on the direction in which we are calculating? Let's test that as well!
&lt;pre&gt;&lt;a class="mentioned-user" href="https://dev.to/test"&gt;@test&lt;/a&gt;
void distanceIsTheSameIfMeasuredInBothDirections() {
    // testing that distance is the same in whatever direction we measure
    double distanceDirection1 = GeometryHelpers.getDistance(-33.926510, 18.364603,-26.208450, 28.040572);
    double distanceDirection2 = GeometryHelpers.getDistance(-26.208450, 28.040572, -33.926510, 18.364603);
    assertEquals(1265065.6094, distanceDirection1, Precision);
    assertEquals(1265065.6094, distanceDirection2, Precision);
}
&lt;/pre&gt;

&lt;h1&gt;Corner cases&lt;/h1&gt;

&lt;p&gt;Great, we have covered some base cases - the main functionality of the method seems to work.&lt;/p&gt;

&lt;p&gt;We can have a cookie now - for going half-way through. 🍪&lt;/p&gt;

&lt;p&gt;Now, let's stretch our code to the limit!&lt;/p&gt;

&lt;p&gt;Thinking about the domain area helps again.&lt;/p&gt;

&lt;p&gt;Our planet is rather a ball than a plane. This means that there is a place where latitude goes from 180 to -180, leaving a "seam" where we should be careful. Math around this area often &lt;a href="https://smartpuffin.com/little-geo-stories-a-tale-of-180th-meridian/" rel="noopener noreferrer"&gt;contains mistakes&lt;/a&gt;. Does our code handle this well?&lt;/p&gt;

&lt;p&gt;A good idea would be to write a test for it, don't you think?&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fh8fnrkw57iiz0k39a20s.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fh8fnrkw57iiz0k39a20s.jpg" alt="Screenshot of a map with a two points on it around the Fiji islands"&gt;&lt;/a&gt;&lt;br&gt;
Working with geo? &lt;a href="http://smartpuffin.com/geo-crash-course/" rel="noopener noreferrer"&gt;Always Check With Fiji!&lt;/a&gt;&lt;/p&gt;

&lt;pre&gt;&lt;a class="mentioned-user" href="https://dev.to/test"&gt;@test&lt;/a&gt;
void distanceAround180thMeridianFiji() {
    double distance = GeometryHelpers.getDistance(-17.947826, 177.221232, -16.603513, -179.779055);
    assertEquals(351826.7740, distance, Precision);
}&lt;/pre&gt;
Upon further thinking, I discovered one more tricky case - distance between two points which have the same latitude; but the longitude is 180 in one point and -180 in the other.
&lt;pre&gt;double distance = GeometryHelpers.getDistance(20, -180, 20, 180);
// Question to you, my reader: what is this distance?&lt;/pre&gt;
Okay, we're done with that weird 180th meridian. We are sure about the 0th meridian though... right? Right? Let's test it too.
&lt;pre&gt;&lt;a class="mentioned-user" href="https://dev.to/test"&gt;@test&lt;/a&gt;
void distanceAround0thMeridianLondon() {
    double distance = GeometryHelpers.getDistance(51.512722, -0.288552, 51.516100, 0.068025);
    assertEquals(24677.4562, distance, Precision);
}&lt;/pre&gt;
What other cases can we come up with? I thought a bit and listed these:
&lt;ul&gt;
    &lt;li&gt;How about poles? Let's calculate a couple of distances in the Arctic and Antarctica.&lt;/li&gt;
    &lt;li&gt;How about from one pole to another?&lt;/li&gt;
    &lt;li&gt;How about the max distance on the planet?&lt;/li&gt;
    &lt;li&gt;How about a really small distance?&lt;/li&gt;
    &lt;li&gt;If both points are absolutely the same, are we getting 0 m distance?&lt;/li&gt;
&lt;/ul&gt;
I'm not adding all these tests here, as it would take too much space. You can find them &lt;a href="https://github.com/ice-lenor/ExampleUnitTests" rel="noopener noreferrer"&gt;in the repo&lt;/a&gt;.

You get the point. Try to think creatively. It's a game of coming up with as many ideas as possible.

And don't be afraid with coming up with "too many ideas". The code is never "tested too well".
&lt;h2&gt;What's inside&lt;/h2&gt;
At this point, it can also help to &lt;a href="https://github.com/ice-lenor/ExampleUnitTests/blob/master/src/main/java/smartpuffin/com/GeometryHelpers.java" rel="noopener noreferrer"&gt;peek inside the code&lt;/a&gt;. Do you have the full coverage? Maybe there are some "ifs" and "elses" in the code that may give you a hint?

Do google "haversine formula" and look at its limitations. We already know about precision. Is there something else that could break? Is there some combination of arguments which can make the code return an invalid value? Brainstorm about it.
&lt;h1&gt;Negative cases&lt;/h1&gt;
Negative cases are cases when the method is supposed to refuse to do its job. It is a controlled failure!

Again, we should remember about the domain area. Latitude and longitude are special values. Latitude is supposed to be defined in exactly [-90, 90] degrees range. Longitude - in [-180, 180] range. This means that in case when we passed an invalid value, our method throws an exception.

Let's add some tests for that!
&lt;pre&gt;&lt;a class="mentioned-user" href="https://dev.to/test"&gt;@test&lt;/a&gt;
void invalidLatitude1TooMuch() {
    assertThrows(IllegalArgumentException.class, () -&amp;gt; {
        GeometryHelpers.getDistance(666, 0, 0, 0);
    });
}
&lt;/pre&gt;

&lt;pre&gt;&lt;a class="mentioned-user" href="https://dev.to/test"&gt;@test&lt;/a&gt;
void invalidLatitude1TooLittle() {
    assertThrows(IllegalArgumentException.class, () -&amp;gt; {
        GeometryHelpers.getDistance(-666, 0, 0, 0);
    });
}
&lt;/pre&gt;

&lt;p&gt;Same tests we'll add for latitude2, and for both longitude parameters.&lt;/p&gt;

&lt;p&gt;We're writing Java here, and the &lt;em&gt;double&lt;/em&gt; parameters can't be null. But if you're using a language where they can, test for it!&lt;/p&gt;

&lt;p&gt;If you're using a dynamically typed language, and you can pass a string instead of the number, test for it!&lt;/p&gt;

&lt;p&gt;Side point: dynamically typed languages will require some more extensive testing than statically typed ones. With the latter, compiler takes care of many things. With the former, it's all in your hands.&lt;/p&gt;

&lt;h1&gt;Wrapping up&lt;/h1&gt;

&lt;p&gt;You can see and download the source code for this tutorial &lt;a href="https://github.com/ice-lenor/ExampleUnitTests/" rel="noopener noreferrer"&gt;here&lt;/a&gt;. Look at it and try to come up with some more useful testing scenarios.&lt;/p&gt;


&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&gt;
      &lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev.to%2Fassets%2Fgithub-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/ice-lenor" rel="noopener noreferrer"&gt;
        ice-lenor
      &lt;/a&gt; / &lt;a href="https://github.com/ice-lenor/ExampleUnitTests" rel="noopener noreferrer"&gt;
        ExampleUnitTests
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      
    &lt;/h3&gt;
  &lt;/div&gt;
  &lt;div class="ltag-github-body"&gt;
    
&lt;div id="readme" class="md"&gt;
&lt;div class="markdown-heading"&gt;
&lt;h1 class="heading-element"&gt;ExampleUnitTests&lt;/h1&gt;
&lt;/div&gt;
&lt;p&gt;This is the source code for the tutorial about writing good unit-test suites.&lt;/p&gt;
&lt;div class="markdown-heading"&gt;
&lt;h1 class="heading-element"&gt;Tutorial&lt;/h1&gt;
&lt;/div&gt;
&lt;p&gt;See the tutorial here:&lt;/p&gt;
&lt;p&gt;&lt;a href="http://smartpuffin.com/unit-tests-tutorial/" rel="nofollow noopener noreferrer"&gt;http://smartpuffin.com/unit-tests-tutorial/&lt;/a&gt;&lt;/p&gt;
&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;What to do with this&lt;/h2&gt;
&lt;/div&gt;
&lt;ol&gt;
&lt;li&gt;Open the tutorial.&lt;/li&gt;
&lt;li&gt;Open &lt;code&gt;GeometryHelpers.java&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Open &lt;code&gt;GeometryHelpersTest1.java&lt;/code&gt;. Review the test structure. Run the test.&lt;/li&gt;
&lt;li&gt;Open &lt;code&gt;GeometryHelpersTest2.java&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Compare the first test in &lt;code&gt;GeometryHelpersTest1.java&lt;/code&gt; with the first test in &lt;code&gt;GeometryHelpersTest2.java&lt;/code&gt;. See how even the smallest pieces of domain area knowledge are important?&lt;/li&gt;
&lt;li&gt;Think about what else you could test. I'm sure there is something I missed!&lt;/li&gt;
&lt;li&gt;Apply the best practices in your own project.&lt;/li&gt;
&lt;li&gt;Like the tutorial? Share, like, subscribe, say thanks. I'll be happy to know it!&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;How to run tests&lt;/h2&gt;

&lt;/div&gt;
&lt;p&gt;I run this with Intellij IDEA and Java 1.8+.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Download the source code.&lt;/li&gt;
&lt;li&gt;Open the folder with the code in Intellij IDEA.&lt;/li&gt;
&lt;li&gt;Open the file &lt;code&gt;GeometryHelpersTest1.java&lt;/code&gt;. You'll see green "Run test" buttons next to line numbers. Press the one next…&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;
  &lt;/div&gt;
  &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/ice-lenor/ExampleUnitTests" rel="noopener noreferrer"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
&lt;/div&gt;


&lt;p&gt;Here's &lt;a href="https://dev.to/ice_lenor/unit-testing-best-practices-27ec"&gt;some followup reading&lt;/a&gt; to learn about best practices in unit testing.&lt;/p&gt;


&lt;div class="ltag__link"&gt;
  &lt;a href="/ice_lenor" class="ltag__link__link"&gt;
    &lt;div class="ltag__link__pic"&gt;
      &lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F17692%2F0c1e08f1-cb6c-4ae7-be0b-3fd5ce00f174.jpg" alt="ice_lenor"&gt;
    &lt;/div&gt;
  &lt;/a&gt;
  &lt;a href="/ice_lenor/unit-testing-best-practices-27ec" class="ltag__link__link"&gt;
    &lt;div class="ltag__link__content"&gt;
      &lt;h2&gt;Unit testing: best practices&lt;/h2&gt;
      &lt;h3&gt;Elena ・ Mar 21 '18&lt;/h3&gt;
      &lt;div class="ltag__link__taglist"&gt;
        &lt;span class="ltag__link__tag"&gt;#unittesting&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#codequality&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#testing&lt;/span&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/a&gt;
&lt;/div&gt;


&lt;p&gt;For your own projects, select the part that would benefit from testing the most - and try to cover it with tests. Think creatively! Make it a challenge, a competition with yourself!&lt;/p&gt;

&lt;p&gt;Unit testing is fun!&lt;/p&gt;

</description>
      <category>unittesting</category>
      <category>codequality</category>
      <category>testing</category>
      <category>problemsolving</category>
    </item>
    <item>
      <title>How To Switch To Software Industry</title>
      <dc:creator>Elena</dc:creator>
      <pubDate>Thu, 15 Aug 2019 11:49:53 +0000</pubDate>
      <link>https://dev.to/ice_lenor/how-to-switch-to-software-industry-18le</link>
      <guid>https://dev.to/ice_lenor/how-to-switch-to-software-industry-18le</guid>
      <description>&lt;p&gt;I am often being asked by friends and acquaintances: how do I switch from my current profession to software development?&lt;/p&gt;

&lt;p&gt;After the third question I decided to write it down.&lt;/p&gt;

&lt;p&gt;All of the following are my personal recommendations, my personal advice. Of course, everyone is different, learning at different speed, motivated by different things. This is how I see things and what I recommend my friends.&lt;/p&gt;

&lt;h2&gt;1. Welcome!&lt;/h2&gt;

&lt;p&gt;First of all: welcome to our field. We need more people like you here.&lt;/p&gt;

&lt;p&gt;Many people nowadays switch their careers, and it is awesome. When you have worked in different fields, you will have a wide range of skills that will come useful.&lt;/p&gt;

&lt;p&gt;For instance, if you did marketing and sales, you know how to talk with people. You will be able to easily to persuade your colleagues to go with your approach or your users to try your product. This is an invaluable skill in software engineering.&lt;/p&gt;

&lt;p&gt;Or, if you were a QA specialist, you already know a lot about common problems in software development. You are quality-oriented and attentive to details. Perhaps, you already know how to code. These skills are going to prove extremely useful.&lt;/p&gt;

&lt;p&gt;Whatever career you were pursuing before, you know how to learn, how to work hard, you are determined and goal-oriented.&lt;/p&gt;

&lt;p&gt;If you really want to and if the circumstances allow you to, do not be afraid to switch. You will definitely succeed.&lt;/p&gt;

&lt;h2&gt;2. What area to choose?&lt;/h2&gt;

&lt;p&gt;Machine learning? Web development? Android apps? Videogames? There are so many different things, and all of them sound so cool.&lt;/p&gt;

&lt;h3&gt;Concentrate on one thing&lt;/h3&gt;

&lt;p&gt;I strongly recommend picking one area and concentrating on it. When you mastered it, you can slowly expand into related areas.&lt;/p&gt;

&lt;p&gt;For example, let's say you always wanted to build websites. It's great! Start with HTML, CSS, Javascript, and at this point you are basically ready to land your dream job or to build your dream website.&lt;/p&gt;

&lt;p&gt;When you have mastered these skills, you can expand further. One way would be to learn backend technologies and skills: a backend language, a database, networking, etc. Another way – to pick up design skills.&lt;/p&gt;

&lt;p&gt;Most likely, you have limited time. (More about this later.) Because of that, you need to pick an industry realistically. It is more realistic to expect to learn only frontend within 6 months than to learn frontend, backend and machine learning skills.&lt;/p&gt;

&lt;p&gt;Along with that, in my opinion, if you start to learn many new things at once, it is going to be very difficult to manage. Brain needs to go step by step.&lt;/p&gt;

&lt;p&gt;It will also take you more time to learn many technologies to the "production-ready" state, and you surely want to start your new career sooner?&lt;/p&gt;

&lt;h3&gt;Go visual&lt;/h3&gt;

&lt;p&gt;Another advice I usually give is to start with something visual. I started learning by building windows applications with Delphi. Simply painting buttons green brought me a lot of joy. (Ah, good times.) I could see my results, I could proudly show my tiny green-buttoned app to other people, and this encouraged me to learn more. It was fun.&lt;/p&gt;

&lt;p&gt;If I were to start with sorting numbers in memory, I am not sure I would be so enchanted by it.&lt;/p&gt;

&lt;p&gt;If you build an app or a website, you will immediately see the results on your screen. This motivates a lot.&lt;/p&gt;

&lt;p&gt;Moreover, sharing your achievements with people is fun! It is easy to show a website to any other person in the world, but to show off your amazing new ML model you need someone who understands what it means. Or, you know, you need to build a website for it:).&lt;/p&gt;

&lt;p&gt;Showing visual results in your CV or on your interview also helps with the job search. The employer can immediately see what your skills are.&lt;/p&gt;

&lt;h3&gt;What do you like?&lt;/h3&gt;

&lt;p&gt;If there is an area that you really like, go for it!&lt;/p&gt;

&lt;p&gt;If you always wanted to make (insert your thing here), start with it. Your motivation is the most important driver on your road to success 🚗.&lt;/p&gt;

&lt;p&gt;For example, if you always wanted to make iOS apps, then start learning that. There is, of course, the possibility of starting to learn how to build desktop apps, then Android apps, then slowly expand to iOS, but if your heart yearns to enrich the Apple ecosystem – why shouldn't you?&lt;/p&gt;

&lt;h3&gt;What do you already know?&lt;/h3&gt;

&lt;p&gt;There is a chance you learned some Python in the university, or perhaps built a couple of pages with HTML+CSS. Great! You won't be starting completely from scratch. Perhaps, it's a good idea to build on these skills. Freshen them up with an online course and see if this helps.&lt;/p&gt;

&lt;h3&gt;What is the demand on the market?&lt;/h3&gt;

&lt;p&gt;What do employers want at the moment?&lt;/p&gt;

&lt;p&gt;If you go for an obscure technology, there is a chance the market for it is so small, there are no positions for you in your city.&lt;/p&gt;

&lt;p&gt;Try to estimate: how useful your skill will be when you're looking for a job.&lt;/p&gt;

&lt;h2&gt;3. Start with fundamentals or practical skills?&lt;/h2&gt;

&lt;p&gt;There are two different approaches.&lt;/p&gt;

&lt;p&gt;The first one – the oldest, the most traditional approach – is to start with fundamentals. You learn assembler, algorithms, math, C, low-level networking, how transistors work and what electrons are. This is very interesting. This takes time. Not all of these skills you are going to apply in your every day job. You will gain a deep understanding of the whole industry and around it, and it costs time.&lt;/p&gt;

&lt;p&gt;The second approach is to learn very practical skills first. It seems rather modern, as bootcamps are just starting to take over the world. But at the same time, it is as old as humanity. Mothers have been passing their knitting and wood carving skills to her daughters and sons for hundreds and thousands of years.&lt;/p&gt;

&lt;p&gt;In this second approach, you would start with learning HtML and you would build a web-page immediately. You don't know yet how exactly browsers work and how the data is stored on the backend side, but you have a visible result.&lt;/p&gt;

&lt;p&gt;The first approach is usually what you do in a university or in college. The second approach is more popular in bootcamps and in self-learning.&lt;/p&gt;

&lt;p&gt;If I were to change the industry right now, I would go for the second approach. I would be willing to see the results right away and to start as soon as possible, and I would be eager to learn the rest on the fly.&lt;/p&gt;

&lt;p&gt;I would be more cautious to spend 2-3 years on learning everything from the beginning. It would be difficult for me to justify setting so much time aside, with the result so far ahead in the future.&lt;/p&gt;

&lt;p&gt;Besides, since you are switching from another profession, you probably already know a lot of fundamentals which are the same across industries. If you have already studied math for your previous engineering job, you don't need to take the same course again.&lt;/p&gt;

&lt;p&gt;Some bootcamps claim that after several months of studying a person will be able to find a new job. Some of them even delay the payment until the student finds a new job with a certain salary level. This seems like a risky approach, but these bootcamps are rather successful. I absolutely believe that a dedicated person is able to do just that: learn practical skills in several months and find a new job.&lt;/p&gt;

&lt;h2&gt;4. Goals and restrictions&lt;/h2&gt;

&lt;p&gt;We all are busy people and have a lot of commitments. Jobs, children, hobbies, friends, budget planning, mortgage, &lt;a href="http://smartpuffin.com/i-hired-freelancers-they-went-over-the-deadline/"&gt;renovations&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;That's why it's important to set some limitations. (And life can set some limitations for you.)&lt;/p&gt;

&lt;p&gt;Try to answer this question:&lt;/p&gt;

&lt;blockquote&gt;What is your specific goal?&lt;/blockquote&gt;

&lt;p&gt;It doesn't have to be a lifetime goal to run a startup with 10 000 employees or to build a rocket for the European Space Agency. Keep it mid-term: say, 6 months or 1 year.&lt;/p&gt;

&lt;p&gt;So, what do you want to achieve within this time limit? And what &lt;em&gt;can&lt;/em&gt; you achieve?&lt;/p&gt;

&lt;p&gt;A reasonable goal would be: "&lt;em&gt;within 1 year I can learn one stack of technologies to a decent level and find a job&lt;/em&gt;". Or, perhaps: "&lt;em&gt;within 6 months I will learn how to build Android apps and will build this app I have an idea for&lt;/em&gt;".&lt;/p&gt;

&lt;p&gt;Next question you have to ask yourself:&lt;/p&gt;

&lt;blockquote&gt;How much time can you dedicate?&lt;/blockquote&gt;

&lt;p&gt;Do you have weekends and evenings at your disposal? Do you only have 2 evenings a week? Maybe you can dedicate your full time to this?&lt;/p&gt;

&lt;p&gt;Of course, it depends on your engagements and your current job.&lt;/p&gt;

&lt;p&gt;You can balance and negotiate your limits. Maybe you have to push your end date by a couple of months or find a way to spend more time on your learning during the week.&lt;/p&gt;

&lt;p&gt;Set a goal realistically. It is only demotivating to expect to finish everything within 2 weeks and then fail.&lt;/p&gt;

&lt;p&gt;This exercise also might help you with picking an industry. If you want to learn machine learning but only have 6 months and 2 evenings a week, perhaps you should start with something simpler.&lt;/p&gt;

&lt;h2&gt;5. Find a mentor&lt;/h2&gt;

&lt;p&gt;A mentor is someone who would oversee your progress and help you with learning. It is helpful if your mentor is someone specialising in the same technology you are learning about, but not strictly necessary.&lt;/p&gt;

&lt;p&gt;They will gently guide your progress, give you materials to learn, assess what your strengths are and what skills you need to pick up next.&lt;/p&gt;

&lt;p&gt;If they're knowledgeable in your specific area, you can also ask your mentor questions about specific problems you're encountering.&lt;/p&gt;

&lt;p&gt;A mentor is especially helpful if you're learning on your own. In a bootcamp or in a university you'll have a lot of people around you ready to teach and help, but if you're following online courses, you might feel lonely and lost sometimes.&lt;/p&gt;

&lt;p&gt;A mentor can introduce you to other people doing similar jobs, or perhaps even refer you to a position in their company.&lt;/p&gt;

&lt;p&gt;An unexpected plus of a mentor is that you would feel responsible to work in order to not let the mentor down. They will hold you responsible, in a way – even if they're the nicest person in the world. They will make you feel accountable.&lt;/p&gt;

&lt;p&gt;Imagine that you met with your mentor, they have sent you an article to read, and next time you meet them, you haven't read the article? Surely, you don't want to let them down this way?&lt;/p&gt;

&lt;h2&gt;6. Consider downsides&lt;/h2&gt;

&lt;p&gt;There are, of course, downsides of learning a lot and switching a job.&lt;/p&gt;

&lt;p&gt;One problem is that learning takes a lot of time and dedication. It is basically a second job. It is easy to not spend your evenings on this new job and watch nature documentaries instead because you are tired.&lt;/p&gt;

&lt;p&gt;Consider what level of career you are on now. If you are to switch your career, you are likely to start from a junior position. This might provide you with less income for a while.&lt;/p&gt;

&lt;p&gt;Software industry is growing. It is dynamic. This means there is a certain level of chaos. New technologies come and go, companies open and close overnight, and what was on the rise yesterday is forgotten today. Because of that, you will have to learn a lot every day, even after you have seemingly "finished" your studies and have found a job. You will not be able to "relax" into a routine.&lt;/p&gt;

&lt;p&gt;Software industry might feel toxic. Despite the fact it is a relatively new area of human knowledge, and it is full of smart educated people, we have already made a mess out of it. Overtime hustle, many rounds of intentionally stressful interviews, and gatekeeping are very common issues. The gender proportion in the industry also leaves me wishing for more equality (based on different reports, only 10-30% of tech positions are held by women in 2019). As a result, people burn out, become sick, leave the industry. Unfortunately, I don't have a specific advice on how to avoid or overcome these problems. It is something our whole industry should become better at, all together. I just want to warn you about these problems in your new profession. It is not all roses and ponies 🦄.&lt;br&gt;
I am not trying to say that the tech industry is the worst. I am sure many other professions suffer from similar problems. On the other hand, the tech industry is wonderful, interesting, lets you make something with your own hands, has many nice and inspiring people.&lt;/p&gt;

&lt;p&gt;Good luck with your choice, and I hope to see you as my colleague soon!&lt;/p&gt;

</description>
      <category>softwaredevelopment</category>
      <category>junior</category>
      <category>begincareer</category>
      <category>careerswitch</category>
    </item>
    <item>
      <title>Nevertheless, Elena Coded</title>
      <dc:creator>Elena</dc:creator>
      <pubDate>Thu, 07 Mar 2019 16:12:37 +0000</pubDate>
      <link>https://dev.to/ice_lenor/nevertheless-elena-coded--1hhe</link>
      <guid>https://dev.to/ice_lenor/nevertheless-elena-coded--1hhe</guid>
      <description>&lt;p&gt;I wrote the first #shecoded post &lt;a href="https://dev.to/ice_lenor/nevertheless-elena-coded--2i5n"&gt;in 2018&lt;/a&gt;, and I liked the opportunity to share, so I'm sharing again.&lt;/p&gt;

&lt;h2&gt;
  
  
  I continued to code in 2019 because...
&lt;/h2&gt;

&lt;p&gt;2019 is my 11th year of coding professionally.&lt;br&gt;
During these years, I did a lot! I built large systems from scratch, and small ones, done bugfixing in huge codebases almost my age, collected user requirements, argued with users:), wrote automated tests, didn't test enough and broke things, added monitoring, broke monitoring, mentored colleagues, grew junior developers, advocated for minorities in tech, led training, led teams, led projects, &lt;br&gt;
became a manager, then a developer again, then a manager, than a developer, built products alone and in a team, built and launched my own projects and charged for them.&lt;/p&gt;

&lt;p&gt;I worked on products which a small number of users uses 24/7 and which millions of users use every day. Enterprise, e-commerce, SaaS and smartphone apps.&lt;/p&gt;

&lt;p&gt;I continue to code because I like how I can create a product out of nothing. It costs me almost nothing, and I can do it alone, but hundreds, thousands, millions of people will find it useful.&lt;/p&gt;

&lt;h2&gt;
  
  
  I deserve credit for...
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Writing &lt;a href="http://smartpuffin.com" rel="noopener noreferrer"&gt;useful articles&lt;/a&gt; about software development 👩‍💻&lt;/li&gt;
&lt;li&gt;Running in-person trainings for my colleagues and helping to share the knowledge 👩‍🏫&lt;/li&gt;
&lt;li&gt;Launching 2 own projects 🥳&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  I hope to see my tech community...
&lt;/h2&gt;

&lt;p&gt;To become diverse and inclusive.&lt;/p&gt;

</description>
      <category>wecoded</category>
    </item>
    <item>
      <title>Geo Crash Course</title>
      <dc:creator>Elena</dc:creator>
      <pubDate>Fri, 11 Jan 2019 09:03:36 +0000</pubDate>
      <link>https://dev.to/ice_lenor/geo-crash-course-5fdj</link>
      <guid>https://dev.to/ice_lenor/geo-crash-course-5fdj</guid>
      <description>&lt;p&gt;What do you need to know when starting in Geo as a developer? Read on to know!&lt;/p&gt;

&lt;p&gt;For a very long time I planned to write this guide on starting in Geo. In this guide, I will:&lt;/p&gt;

&lt;ul&gt;
    &lt;li&gt;Tell you that Earth is not flat (SHOCK!) and why that's very inconvenient;&lt;/li&gt;
    &lt;li&gt;Define common terms (What's projection? There's also a coordinate system?.. OGC, OSM, WKT, WGS, ESPG?);&lt;/li&gt;
    &lt;li&gt;Teach you All Things You Need To Know™ to become a geo-developer and build things for Geo or using Geo;&lt;/li&gt;
    &lt;li&gt;Explain popular caveats - Dos and Don'ts - when working with Geo;&lt;/li&gt;
    &lt;li&gt;Give you an overview of geo-technologies, industry standards, databases, libraries;&lt;/li&gt;
    &lt;li&gt;Give you references for further reading.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I ran this workshop for my colleagues who are interested in Geo, and it was a great success! I hope you enjoy it as well.&lt;/p&gt;

&lt;p&gt;Good luck with your journey around the globe!&lt;/p&gt;

&lt;p&gt;&lt;iframe src="https://www.slideshare.net/slideshow/embed_code/key/EhDjrrN57Qwxwt" alt="EhDjrrN57Qwxwt on slideshare.net" width="100%" height="487"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

</description>
      <category>geo</category>
      <category>guide</category>
      <category>workshop</category>
      <category>geodata</category>
    </item>
    <item>
      <title>How I Deal With Bad User Feedback</title>
      <dc:creator>Elena</dc:creator>
      <pubDate>Mon, 17 Dec 2018 17:41:16 +0000</pubDate>
      <link>https://dev.to/ice_lenor/how-i-deal-with-bad-user-feedback-3437</link>
      <guid>https://dev.to/ice_lenor/how-i-deal-with-bad-user-feedback-3437</guid>
      <description>&lt;p&gt;This post was originally published in my blog &lt;a href="http://smartpuffin.com/bad-user-feedback/" rel="noopener noreferrer"&gt;smartpuffin.com&lt;/a&gt;.&lt;/p&gt;




&lt;p&gt;We all know this feeling. You spend your precious time to develop an awesome project, polish it to perfection, and carefully roll it out for your users.&lt;/p&gt;

&lt;p&gt;And then they tell you:&lt;/p&gt;

&lt;blockquote&gt;

★☆☆☆☆

BOO! Worst app EVER! Do NoT UsE!!!11
&lt;/blockquote&gt;

&lt;p&gt;&lt;a href="https://play.google.com/store/apps/details?id=ice.lenor.nicewordplacer.app" rel="noopener noreferrer"&gt;My WordCloud app&lt;/a&gt; has 1.7M users and 5K reviews on Google Play. The average review score is 4.5★. This means that many users love the app, but some don't.&lt;/p&gt;

&lt;p&gt;I used to dread bad reviews! First ones were a nightmare. I was scared to read all reviews in fear that there is a negative one. Upon seeing one, I used to spend days feeling miserable and unfairly judged.&lt;/p&gt;

&lt;p&gt;But I couldn't feel miserable forever. So after some time developed these rules and I started to follow them.&lt;/p&gt;

&lt;h2&gt;Constructive bad reviews&lt;/h2&gt;

&lt;p&gt;When the review is constructive, I usually reply.&lt;/p&gt;

&lt;p&gt;If they couldn't understand how to use a particular feature, I write an instruction for them.&lt;/p&gt;

&lt;p&gt;It also helps other users who might experience the same problem. This is valuable feedback — maybe I should reconsider the feature or its UI if it is unclear for many people.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fd770vubnoyz6pioqw66x.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fd770vubnoyz6pioqw66x.jpg"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If they expected a feature that's not present, I explain it and promise to consider it in the future.&lt;/p&gt;

&lt;p&gt;This doesn't mean I'll add the said feature. Perhaps, it doesn't fit my product vision, or maybe there are technical constraints. So I don't promise to implement — I just promise to consider. Still, this is valuable feedback, and sometimes these ideas are really good — even though they make me sad for a little while.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fu4ekarsrpbb6ov898kp9.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fu4ekarsrpbb6ov898kp9.jpg"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;Destructive reviews&lt;/h2&gt;

&lt;p&gt;If the review is like "worst app ever!!111", I don't reply. There is no point in replying. I learned to grow thick skin against these types of reviews. Some people just want to be negative on the internet. It doesn't say anything about you, your product, or the quality of it. Some percentage of reviews will be like that anyways, for any app, however great it is.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fav1lct6coro3feqivrh9.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fav1lct6coro3feqivrh9.jpg"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;Reviews complaining about how stuff isn't free&lt;/h2&gt;

&lt;p&gt;Sometimes the only complaint is that some features in the app are paid.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fqykbspjo1are1pg3gsp1.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fqykbspjo1are1pg3gsp1.jpg"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Or like this:&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2F16jkxppwlh5ghtjlc656.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2F16jkxppwlh5ghtjlc656.jpg"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;To such reviews, I usually don't reply. I can't help the user in any way. This just means my product is not for them.&lt;/p&gt;

&lt;p&gt;I only posted an answer once, and here it is:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fcyw5zjr295j3kwmq0rx9.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fcyw5zjr295j3kwmq0rx9.jpg"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;Positive reviews&lt;/h2&gt;

&lt;p&gt;It warms my heart when people &lt;a href="http://smartpuffin.com/?p=373&amp;amp;preview=true" rel="noopener noreferrer"&gt;find my work useful&lt;/a&gt;!&lt;/p&gt;

&lt;p&gt;To such reviews on Google Play, I usually reply "thank you" or nothing at all, since there are sometimes too many reviews — but I really do appreciate them.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fsbnzekchg32npom3p2og.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fsbnzekchg32npom3p2og.jpg"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt; &lt;/p&gt;

&lt;p&gt;I reply to all emails though. An email means that a person took time to message me personally, and I appreciate that.&lt;/p&gt;

&lt;p&gt;I even got &lt;a href="http://smartpuffin.com/wordcloud-i-got-a-present/" rel="noopener noreferrer"&gt;a physical present from a happy user&lt;/a&gt; once! That made me sooo happy!..&lt;/p&gt;

&lt;h2&gt;"This is not about my app" reviews&lt;/h2&gt;

&lt;p&gt;And now, a funny story. I sometimes get bad reviews that are about &lt;em&gt;&lt;strong&gt;OTHER&lt;/strong&gt;&lt;/em&gt; apps :).&lt;/p&gt;

&lt;p&gt;There are a bunch of "impostor" apps that mimic mine. They have the same name and a similar UI, but are filled with lots of annoying ads and often don't work. So people download them, try to use, fail, get angry, and type the reviews for my app because it's on top in the Google Play when you search for "Word Cloud".&lt;/p&gt;

&lt;p&gt;I even got a couple of emails from people using these impostor apps on &lt;em&gt;&lt;strong&gt;OTHER PLATFORMS&lt;/strong&gt;&lt;/em&gt; — such as iOS, while my app is Android-only. (So far.)&lt;/p&gt;

&lt;p&gt;There is nothing I can do against these reviews, or these apps for that matter — Google and Apple don't help much in fighting them. I find consolation in the thought that my app is so great it's worth copying :).&lt;/p&gt;

</description>
      <category>users</category>
      <category>feedback</category>
      <category>customersupport</category>
    </item>
    <item>
      <title>Writing Good Unit Tests: A Step By Step Tutorial</title>
      <dc:creator>Elena</dc:creator>
      <pubDate>Wed, 21 Nov 2018 22:01:53 +0000</pubDate>
      <link>https://dev.to/ice_lenor/writing-good-unit-tests-a-step-by-step-tutorial-14kj</link>
      <guid>https://dev.to/ice_lenor/writing-good-unit-tests-a-step-by-step-tutorial-14kj</guid>
      <description>&lt;p&gt;This post was originally published in my blog &lt;a href="http://smartpuffin.com/unit-tests-tutorial/" rel="noopener noreferrer"&gt;smartpuffin.com&lt;/a&gt;.&lt;/p&gt;




&lt;p&gt;Let's imagine we just wrote a method calculating distance between two points on our planet. And let's imagine we want to test it as well as possible. How do we come up with test cases? And what exactly do we need to test?&lt;/p&gt;

&lt;p&gt;Bonus: learn a surprising fact about the Fiji islands. 🇫🇯&lt;/p&gt;

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

&lt;p&gt;I assume you are already familiar with the concepts of unit testing. I'll be using Java and JUnit, but don't worry if you're not familiar with them: the purpose of this tutorial is to learn to write fuller test suites. You'll pick up platform-specific things on the fly.&lt;/p&gt;

&lt;p&gt;Here is a link &lt;a href="https://github.com/ice-lenor/ExampleUnitTests" rel="noopener noreferrer"&gt;to the repository&lt;/a&gt; where I have put the full source code for this post. You can download it and look at it while reading, or look at it afterwards.&lt;/p&gt;

&lt;p&gt;And here is my previous article on unit testing topic explaining &lt;a href="https://dev.to/ice_lenor/unit-testing-best-practices-27ec"&gt;best practices in unit testing&lt;/a&gt; more widely.&lt;/p&gt;

&lt;p&gt;Let's go!&lt;/p&gt;

&lt;h1&gt;Positive cases&lt;/h1&gt;

&lt;p&gt;Let's start with thinking about our method as of a black box.&lt;/p&gt;

&lt;p&gt;We have this API:&lt;/p&gt;

&lt;pre&gt;
// Returns distance in meters using haversine formula
double getDistance(double latitude1, double longitude1, double latitude2, double longitude2);
&lt;/pre&gt;

&lt;p&gt;What can we test?&lt;/p&gt;

&lt;h2&gt;Putting yourself in a testing mindset&lt;/h2&gt;

&lt;p&gt;You need to switch from being a developer to being a tester now. This means you have to stop trusting yourself. You can't know your code is working if you didn't test it!&lt;/p&gt;

&lt;p&gt;If you tested it manually, you don't know if it's going to work next time someone makes a change - in your code or close to it.&lt;/p&gt;

&lt;p&gt;Moreover, you can be sure that whatever code you build on top of this well-tested piece, you have one less problem to worry about.&lt;/p&gt;

&lt;p&gt;The feeling of security you have when your code is well-tested is incredible. You can refactor freely and develop new features further - and be sure your old code is not going to break.&lt;/p&gt;

&lt;p&gt;Promise yourself a treat if you find a bug. But do be careful: too many cookies are bad for your health.&lt;/p&gt;

&lt;h2&gt;First test&lt;/h2&gt;

&lt;p&gt;Okay, we are ready to test! What should we test first?&lt;/p&gt;

&lt;p&gt;The very first thing that comes to mind, is:&lt;/p&gt;

&lt;blockquote&gt;Calculate the distance between two points and compare with the true real number calculated manually. If they match, all is well!&lt;/blockquote&gt;

&lt;p&gt;And this is a great testing strategy. Let's write some tests for that.&lt;/p&gt;

&lt;p&gt;I'll pick a couple of points: one in the very north of the Netherlands, one - in the very south. Practically, I want to measure the country from top to bottom.&lt;/p&gt;

&lt;p&gt;I clicked at a couple of points on the map and got this:&lt;/p&gt;

&lt;pre&gt;Point 1: latitude = 53.478612, longitude = 6.250578.
Point 2: latitude = 50.752342, longitude = 5.916981.
&lt;/pre&gt;

&lt;p&gt;I have used an external website to calculate the distance and got 304001.021046 meters. That means the Netherlands are 304km long!&lt;/p&gt;

&lt;p&gt;Now, how do we use this?&lt;/p&gt;

&lt;h2&gt;Thinking about domain area&lt;/h2&gt;

&lt;p&gt;We need to think about domain area-specific things. Not all of them are obvious from the code: some of them depend on the area, some - on the future plans.&lt;/p&gt;

&lt;p&gt;In our example, the returned distance is in meters, and it's a double.&lt;/p&gt;

&lt;p&gt;We know that a double is prone to rounding errors. Moreover, we know that the method used in this calculation - the haversine formula - is somewhat imprecise for our oh-so-complex planet. It is enough for our application now, but perhaps, we'll want to replace it with higher-precision calculation.&lt;/p&gt;

&lt;p&gt;All this makes us think that we should compare our calculated value with our expected value with some precision.&lt;/p&gt;

&lt;p&gt;Let's pick some value that is good for our domain area. To do that, we can remember about our domain area and requirements again. Would 1mm be fine? Probably it would.&lt;/p&gt;

&lt;p&gt;And here is our first test!&lt;/p&gt;

&lt;pre&gt;double Precision = 0.001; // We are comparing calculated distance using 1mm precision
...
&lt;a class="mentioned-user" href="https://dev.to/test"&gt;@test&lt;/a&gt;
void distanceTheNetherlandsNorthToSouth() {
    double distance = GeometryHelpers.getDistance(53.478612, 6.250578, 50.752342, 5.916981);
    assertEquals(304001.0210, distance, Precision);
}
&lt;/pre&gt;

&lt;p&gt;Let's run this test and make sure it passes. Yay!&lt;/p&gt;

&lt;h2&gt;More tests&lt;/h2&gt;

&lt;p&gt;We calculated the distance across the Netherlands. But of course, it is a nice idea to double-check and to triple-check.&lt;/p&gt;

&lt;p&gt;Your tests should vary - this helps you cast a wider net for these pesky bugs!&lt;/p&gt;

&lt;p&gt;Let's find some more nice points. How about we learn how wide Australia is?&lt;/p&gt;

&lt;pre&gt;&lt;a class="mentioned-user" href="https://dev.to/test"&gt;@test&lt;/a&gt;
void distanceAustraliaWestToEast() {
    double distance = GeometryHelpers.getDistance(-23.939607, 113.585605, -28.293166, 153.718989);
    assertEquals(4018083.0398, distance, Precision);
}&lt;/pre&gt;
Or how far is it from Capetown to Johannesburg?
&lt;pre&gt;&lt;a class="mentioned-user" href="https://dev.to/test"&gt;@test&lt;/a&gt;
void distanceFromCapetownToJohannesburg() {
    double distance = GeometryHelpers.getDistance(-33.926510, 18.364603,-26.208450, 28.040572);
    assertEquals(1265065.6094, distance, Precision);
}&lt;/pre&gt;
Now that we think about that: are we sure that the distance doesn't depend on the direction in which we are calculating? Let's test that as well!
&lt;pre&gt;&lt;a class="mentioned-user" href="https://dev.to/test"&gt;@test&lt;/a&gt;
void distanceIsTheSameIfMeasuredInBothDirections() {
    // testing that distance is the same in whatever direction we measure
    double distanceDirection1 = GeometryHelpers.getDistance(-33.926510, 18.364603,-26.208450, 28.040572);
    double distanceDirection2 = GeometryHelpers.getDistance(-26.208450, 28.040572, -33.926510, 18.364603);
    assertEquals(1265065.6094, distanceDirection1, Precision);
    assertEquals(1265065.6094, distanceDirection2, Precision);
}
&lt;/pre&gt;

&lt;h1&gt;Corner cases&lt;/h1&gt;

&lt;p&gt;Great, we have covered some base cases - the main functionality of the method seems to work.&lt;/p&gt;

&lt;p&gt;We can have a cookie now - for going half-way through. 🍪&lt;/p&gt;

&lt;p&gt;Now, let's stretch our code to the limit!&lt;/p&gt;

&lt;p&gt;Thinking about the domain area helps again.&lt;/p&gt;

&lt;p&gt;Our planet is rather a ball than a plane. This means that there is a place where latitude goes from 180 to -180, leaving a "seam" where we should be careful. Math around this area often &lt;a href="https://smartpuffin.com/little-geo-stories-a-tale-of-180th-meridian/" rel="noopener noreferrer"&gt;contains mistakes&lt;/a&gt;. Does our code handle this well?&lt;/p&gt;

&lt;p&gt;A good idea would be to write a test for it, don't you think?&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fh8fnrkw57iiz0k39a20s.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fh8fnrkw57iiz0k39a20s.jpg" alt="Screenshot of a map with a two points on it around the Fiji islands"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;pre&gt;&lt;a class="mentioned-user" href="https://dev.to/test"&gt;@test&lt;/a&gt;
void distanceAround180thMeridianFiji() {
    double distance = GeometryHelpers.getDistance(-17.947826, 177.221232, -16.603513, -179.779055);
    assertEquals(351826.7740, distance, Precision);
}&lt;/pre&gt;
Upon further thinking, I discovered one more tricky case - distance between two points which have the same latitude; but the longitude is 180 in one point and -180 in the other.
&lt;pre&gt;double distance = GeometryHelpers.getDistance(20, -180, 20, 180);
// Question to you, my reader: what is this distance?&lt;/pre&gt;
Okay, we're done with that weird 180th meridian. We are sure about the 0th meridian though... right? Right? Let's test it too.
&lt;pre&gt;&lt;a class="mentioned-user" href="https://dev.to/test"&gt;@test&lt;/a&gt;
void distanceAround0thMeridianLondon() {
    double distance = GeometryHelpers.getDistance(51.512722, -0.288552, 51.516100, 0.068025);
    assertEquals(24677.4562, distance, Precision);
}&lt;/pre&gt;
What other cases can we come up with? I thought a bit and listed these:
&lt;ul&gt;
    &lt;li&gt;How about poles? Let's calculate a couple of distances in the Arctic and Antarctica.&lt;/li&gt;
    &lt;li&gt;How about from one pole to another?&lt;/li&gt;
    &lt;li&gt;How about max distance on the planet?&lt;/li&gt;
    &lt;li&gt;How about a really small distance?&lt;/li&gt;
    &lt;li&gt;If both points are absolutely the same, are we getting 0 m distance?&lt;/li&gt;
&lt;/ul&gt;
I'm not adding all these tests here, as it would take too much space. You can find them &lt;a href="https://github.com/ice-lenor/ExampleUnitTests" rel="noopener noreferrer"&gt;in the repo&lt;/a&gt;.

You get the point. Try to think creatively. It's a game of coming up with as many ideas as possible.

And don't be afraid with coming up with "too many ideas". The code is never "tested too well".
&lt;h2&gt;What's inside&lt;/h2&gt;
At this point, it can also help to &lt;a href="https://github.com/ice-lenor/ExampleUnitTests/blob/master/src/main/java/smartpuffin/com/GeometryHelpers.java" rel="noopener noreferrer"&gt;peek inside the code&lt;/a&gt;. Do you have the full coverage? Maybe there are some "ifs" and "elses" in the code that may give you a hint?

Do google "haversine formula" and look at its limitations. We already know about precision. Is there something else that could break? Is there some combination of arguments which can make the code return an invalid value? Brainstorm about it.
&lt;h1&gt;Negative cases&lt;/h1&gt;
Negative cases are cases when the method is supposed to refuse to do its job. It is a controlled failure!

Again, we should remember about the domain area. Latitude and longitude are special values. Latitude is supposed to be defined in exactly [-90, 90] degrees range. Longitude - in [-180, 180] range. This means that in case when we passed an invalid value, our method throws an exception.

Let's add some tests for that!
&lt;pre&gt;&lt;a class="mentioned-user" href="https://dev.to/test"&gt;@test&lt;/a&gt;
void invalidLatitude1TooMuch() {
    assertThrows(IllegalArgumentException.class, () -&amp;gt; {
        GeometryHelpers.getDistance(666, 0, 0, 0);
    });
}
&lt;/pre&gt;

&lt;pre&gt;&lt;a class="mentioned-user" href="https://dev.to/test"&gt;@test&lt;/a&gt;
void invalidLatitude1TooLittle() {
    assertThrows(IllegalArgumentException.class, () -&amp;gt; {
        GeometryHelpers.getDistance(-666, 0, 0, 0);
    });
}
&lt;/pre&gt;

&lt;p&gt;Same tests we'll add for latitude2, and for both longitude parameters.&lt;/p&gt;

&lt;p&gt;We're writing Java here, and the &lt;em&gt;double&lt;/em&gt; parameters can't be null. But if you're using a language where they can, test for it!&lt;/p&gt;

&lt;p&gt;If you're using a dynamically typed language, and you can pass a string instead of the number, test for it!&lt;/p&gt;

&lt;p&gt;Side point: dynamically typed languages will require some more extensive testing than statically typed ones. With the latter, compiler takes care of many things. With the former, it's all in your hands.&lt;/p&gt;

&lt;h1&gt;Wrapping up&lt;/h1&gt;

&lt;p&gt;You can see and download the source code for this tutorial &lt;a href="https://github.com/ice-lenor/ExampleUnitTests/" rel="noopener noreferrer"&gt;here&lt;/a&gt;. Look at it and try to come up with some more useful testing scenarios.&lt;/p&gt;


&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&gt;
      &lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev.to%2Fassets%2Fgithub-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/ice-lenor" rel="noopener noreferrer"&gt;
        ice-lenor
      &lt;/a&gt; / &lt;a href="https://github.com/ice-lenor/ExampleUnitTests" rel="noopener noreferrer"&gt;
        ExampleUnitTests
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      
    &lt;/h3&gt;
  &lt;/div&gt;
  &lt;div class="ltag-github-body"&gt;
    
&lt;div id="readme" class="md"&gt;
&lt;div class="markdown-heading"&gt;
&lt;h1 class="heading-element"&gt;ExampleUnitTests&lt;/h1&gt;
&lt;/div&gt;
&lt;p&gt;This is the source code for the tutorial about writing good unit-test suites.&lt;/p&gt;
&lt;div class="markdown-heading"&gt;
&lt;h1 class="heading-element"&gt;Tutorial&lt;/h1&gt;
&lt;/div&gt;
&lt;p&gt;See the tutorial here:&lt;/p&gt;
&lt;p&gt;&lt;a href="http://smartpuffin.com/unit-tests-tutorial/" rel="nofollow noopener noreferrer"&gt;http://smartpuffin.com/unit-tests-tutorial/&lt;/a&gt;&lt;/p&gt;
&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;What to do with this&lt;/h2&gt;
&lt;/div&gt;
&lt;ol&gt;
&lt;li&gt;Open the tutorial.&lt;/li&gt;
&lt;li&gt;Open &lt;code&gt;GeometryHelpers.java&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Open &lt;code&gt;GeometryHelpersTest1.java&lt;/code&gt;. Review the test structure. Run the test.&lt;/li&gt;
&lt;li&gt;Open &lt;code&gt;GeometryHelpersTest2.java&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Compare the first test in &lt;code&gt;GeometryHelpersTest1.java&lt;/code&gt; with the first test in &lt;code&gt;GeometryHelpersTest2.java&lt;/code&gt;. See how even the smallest pieces of domain area knowledge are important?&lt;/li&gt;
&lt;li&gt;Think about what else you could test. I'm sure there is something I missed!&lt;/li&gt;
&lt;li&gt;Apply the best practices in your own project.&lt;/li&gt;
&lt;li&gt;Like the tutorial? Share, like, subscribe, say thanks. I'll be happy to know it!&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;How to run tests&lt;/h2&gt;

&lt;/div&gt;
&lt;p&gt;I run this with Intellij IDEA and Java 1.8+.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Download the source code.&lt;/li&gt;
&lt;li&gt;Open the folder with the code in Intellij IDEA.&lt;/li&gt;
&lt;li&gt;Open the file &lt;code&gt;GeometryHelpersTest1.java&lt;/code&gt;. You'll see green "Run test" buttons next to line numbers. Press the one next…&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;
  &lt;/div&gt;
  &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/ice-lenor/ExampleUnitTests" rel="noopener noreferrer"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
&lt;/div&gt;


&lt;p&gt;Here's &lt;a href="https://dev.to/ice_lenor/unit-testing-best-practices-27ec"&gt;some followup reading&lt;/a&gt; to learn about best practices in unit testing.&lt;/p&gt;


&lt;div class="ltag__link"&gt;
  &lt;a href="/ice_lenor" class="ltag__link__link"&gt;
    &lt;div class="ltag__link__pic"&gt;
      &lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F17692%2F0c1e08f1-cb6c-4ae7-be0b-3fd5ce00f174.jpg" alt="ice_lenor"&gt;
    &lt;/div&gt;
  &lt;/a&gt;
  &lt;a href="/ice_lenor/unit-testing-best-practices-27ec" class="ltag__link__link"&gt;
    &lt;div class="ltag__link__content"&gt;
      &lt;h2&gt;Unit testing: best practices&lt;/h2&gt;
      &lt;h3&gt;Elena ・ Mar 21 '18&lt;/h3&gt;
      &lt;div class="ltag__link__taglist"&gt;
        &lt;span class="ltag__link__tag"&gt;#unittesting&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#codequality&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#testing&lt;/span&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/a&gt;
&lt;/div&gt;


&lt;p&gt;For your own projects, select the part that would benefit from testing the most - and try to cover it with tests. Think creatively! Make it a challenge, a competition with yourself!&lt;/p&gt;

&lt;p&gt;Unit testing is fun!&lt;/p&gt;

</description>
      <category>unittesting</category>
      <category>codequality</category>
      <category>testing</category>
      <category>problemsolving</category>
    </item>
    <item>
      <title>When Not To A/B Test</title>
      <dc:creator>Elena</dc:creator>
      <pubDate>Wed, 17 Oct 2018 22:01:47 +0000</pubDate>
      <link>https://dev.to/ice_lenor/when-not-to-ab-test-4cc7</link>
      <guid>https://dev.to/ice_lenor/when-not-to-ab-test-4cc7</guid>
      <description>&lt;p&gt;&lt;em&gt;This article has been first published in my blog &lt;a href="http://smartpuffin.com/when-not-to-ab-test/"&gt;smartpuffin.com&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;



&lt;p&gt;As I plowed my way through &lt;a href="https://dev.to/ice_lenor/ab-testing-introduction-3jpd"&gt;A/B testing of more than 300 features&lt;/a&gt;, I was wondering: are there any cases when you don't want to A/B test?&lt;/p&gt;

&lt;p&gt;It seems like an easy way to understand if the users love your new feature. If you introduce it to half the users, are they buying your product more than the other half? If yes, show it to all users. If no, scrap it and build something else.&lt;/p&gt;

&lt;p&gt;Are there any cases when you don't want that conversion increase, but you'd rather have a feature right away?&lt;/p&gt;

&lt;p&gt;Having thought about it, I came up with this list.&lt;/p&gt;

&lt;h1&gt;1. Legal&lt;/h1&gt;

&lt;p&gt;Your Legal department wants you to immediately put an important message in your footer.&lt;/p&gt;

&lt;p&gt;Perhaps, you cannot legally sell your products in some country.&lt;/p&gt;

&lt;p&gt;Maybe, a lawsuit requires you to display the user agreement in full, or to change an icon, or to remove a copyrighted photo, or to display some important information to your customers before they buy.&lt;/p&gt;

&lt;p&gt;You don't mess with Legal. You really have to add this feature.&lt;/p&gt;

&lt;h1&gt;2. Accessibility&lt;/h1&gt;

&lt;p&gt;You change colors so that color-blind people can use your website.&lt;/p&gt;

&lt;p&gt;You increase font size for people who are visually impaired to use your app easier.&lt;/p&gt;

&lt;p&gt;Add alt-text to images. Improve content for screen readers. Increase text contrast. Add subtitles to your video.&lt;/p&gt;

&lt;p&gt;Yes, people with disabilities might actually convert better after all these improvements, but since they are a small fraction of all users, it won't be visible on your graphs.&lt;/p&gt;

&lt;p&gt;And overall, this seems like a decent thing to do.&lt;/p&gt;

&lt;h1&gt;3. Moral choice&lt;/h1&gt;

&lt;p&gt;Your website displays a large banner about "great discounts", but it is out of date, and they are not applicable anymore.&lt;/p&gt;

&lt;p&gt;Maybe your algorithm for calculating the "lowest price" is broken and displays this motivational message on all products. Users start to suspect something when all prices are the lowest.&lt;/p&gt;

&lt;p&gt;Perhaps, you advertise "free shipping", but only in fine print the user can see it's domestic only. This is a nasty surprise at checkout.&lt;/p&gt;

&lt;p&gt;Maybe you display ads and suddenly see something indecent. Or you feature other people's articles, and find out they posted something that strongly requires immediate moderation.&lt;/p&gt;

&lt;p&gt;This is worth fixing, even if it doesn't bring your company more money.&lt;/p&gt;

&lt;h1&gt;4. Bugfix&lt;/h1&gt;

&lt;p&gt;Your layout is broken. A button isn't working. A link leads to a non-existing page. The "Add to cart" button doesn't add a product to the cart. (Well, this last one will be noticed immediately.)&lt;/p&gt;

&lt;p&gt;You can fix this right away.&lt;/p&gt;

&lt;h1&gt;5. New product&lt;/h1&gt;

&lt;p&gt;Sometimes, people can be too careful in introducing new products or large new features.&lt;/p&gt;

&lt;p&gt;You did your user research. You talked with your customers. You know the demand. But you're reluctant to make this large step. You think: maybe I can introduce this large feature as a series of small changes, and test them all for conversion increase.&lt;/p&gt;

&lt;p&gt;But sometimes it is not enough. Sometimes a large feature needs to be introduced in full, so that the users could try the full experience.&lt;/p&gt;

&lt;p&gt;It is especially challenging when you don't have the control group. If it's a new product, who do you compare your users (that is, the treatment group) to?&lt;/p&gt;

&lt;p&gt;Absolute numbers might work better in this case: for example, what percentage of users are becoming customers. After establishing this number, A/B tests can be run to improve it.&lt;/p&gt;

&lt;h1&gt;6. Small number of users&lt;/h1&gt;

&lt;p&gt;If the number of users is not enough to have a decent sample size, what is the point of running an A/B test?&lt;/p&gt;

&lt;h1&gt;7. Professional users&lt;/h1&gt;

&lt;p&gt;With these users, you have to be extremely careful. Imagine you write software for call-center people, whose bonus depends on how many calls per day they are taking.&lt;/p&gt;

&lt;p&gt;Do you really want to run random A/B tests on that software, knowing that someone's compensation depends on chance?&lt;/p&gt;

&lt;p&gt;Users might become less productive if a feature they are using 3000 times per day changes its appearance every now and then. If you use something very often, it becomes automatic, and you become very sensitive to changes. Imagine someone experiments with the key combination to save a file or to exit vim. You'll become many times less productive because of that small change - and very, very annoyed.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Yes, I really have worked on software where a particular feature was &lt;a href="http://smartpuffin.com/gis-system-our-requirements/#3000-objects"&gt;used up to 3000 times per day&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;For professional users, a better approach is more often to introduce a change after having spoken with them. Ask them about their needs. Collect their requirements. Agree with them on a change. Document it. Give them a beta to try. Collect feedback. Improve. Release.&lt;/p&gt;

&lt;h1&gt;Conclusion&lt;/h1&gt;

&lt;p&gt;You might still want to introduce all listed changes as experiments. The reason for that would be to see if you're creating any negative impact with the change. Perhaps, your increased contrast doesn't work on some devices or in some browsers? Maybe you broke your cart completely when fixing that "add to cart" button? Perhaps, you have accidentally forbidden selling the product in all countries? Then you will see it in your metrics. An A/B test will act as a feature switch. You'll be able to quickly turn your feature off, fix, and retry.&lt;/p&gt;

&lt;p&gt;But for many cases I listed, it wouldn't be the best decision to wait weeks and months to get a large sample size, then compare conversion - and turn the feature off if the conversion growth is not enough.&lt;/p&gt;

&lt;p&gt;Some features deserve to live regardless of conversion increase they bring.&lt;/p&gt;

</description>
      <category>abtesting</category>
      <category>product</category>
      <category>experimentation</category>
      <category>business</category>
    </item>
    <item>
      <title>The Hunch: 4 Times I Felt It And 1 When I Didn't, And What Were The Consequences</title>
      <dc:creator>Elena</dc:creator>
      <pubDate>Wed, 29 Aug 2018 17:00:00 +0000</pubDate>
      <link>https://dev.to/ice_lenor/the-hunch-4-times-i-felt-it-and-1-when-i-didnt-and-what-were-the-consequences-13cd</link>
      <guid>https://dev.to/ice_lenor/the-hunch-4-times-i-felt-it-and-1-when-i-didnt-and-what-were-the-consequences-13cd</guid>
      <description>&lt;p&gt;&lt;i&gt;This post was originally published in my blog &lt;a href="http://smartpuffin.com/the-hunch-examples/"&gt;smartpuffin.com&lt;/a&gt;.&lt;/i&gt;&lt;/p&gt;




&lt;p&gt;I sometimes have this feeling: &lt;i&gt;&lt;a href="https://dev.to/ice_lenor/problem-solving-a-hunch-356i"&gt;The Hunch&lt;/a&gt;&lt;/i&gt;&lt;span&gt;&lt;i&gt;&lt;a href="http://smartpuffin.com/problem-solving-a-hunch/"&gt;™&lt;/a&gt;&lt;/i&gt;&lt;/span&gt;. It's when I sense there is something wrong with the project, with the requirement, or with the feature, even when everyone else is sure all is well.&lt;/p&gt;

&lt;p&gt;When I sense this, I feel like a dog who picked up the scent. I follow the scent by asking questions, until I get my answer.&lt;/p&gt;

&lt;p&gt;Here's how it happens.&lt;/p&gt;

&lt;h2&gt;Dataset Extension&lt;/h2&gt;

&lt;p&gt;Our Dev team asked the Data team to collect some new data, in order to extend our already existing dataset. We had 1000 items, and we wanted 5000 more. We told them how we want it to be prioritised, we agred on the timeline, and we left reassured.&lt;/p&gt;

&lt;p&gt;The first deliverable was ready. They sent is a huge shared spreadsheet with 1 thousand rows. We were happy, since it meant we would soon have twice more data than before!..&lt;/p&gt;

&lt;p&gt;I wrote a script to upload all this new data to our database. I found some small problems in the data, such as columns mixed up, or string values in numerical columns, and the Data team fixed them quickly. Nothing serious.&lt;/p&gt;

&lt;p&gt;All was ready. I was (literally!) holding my finger above the Enter key, pressing which would upload the data to the live servers.&lt;/p&gt;

&lt;p&gt;But I hesitated. I had &lt;i&gt;The Hunch&lt;/i&gt;&lt;span&gt;&lt;i&gt;™&lt;/i&gt;&lt;/span&gt;. And so I didn't press enter.&lt;/p&gt;

&lt;p&gt;I asked the Data team the very last (or so I thought) question:&lt;/p&gt;

&lt;p&gt;"Do I understand it right: all this is the very new data? When we upload it, we'll have 2 thousand items, is that correct?"&lt;/p&gt;

&lt;p&gt;No, they told me. They had decided to execute a clean-up project along with collecting new data for us. 600 rows in this spreadsheet are &lt;i&gt;to be updated.&lt;/i&gt; Only 400 are to be created.&lt;/p&gt;

&lt;p&gt;It took me a minute to gather my thoughts. Not a single time was the clean-up mentioned to us before. How happy I was that I asked!.. Had I uploaded the data, we would have gotten 600 duplicated items.&lt;/p&gt;

&lt;p&gt;How, asked I, do I understand from the spreadsheet which items are new and which are old? Surely you have an ID column for updates?&lt;/p&gt;

&lt;p&gt;No, they told me. There was no such column. There is no other way to understand that. They simply didn't realise we will have to know which exact items have to be updated - until I asked.&lt;/p&gt;

&lt;p&gt;Long story short, after much discussion, they added the ID column for us, marked the updated items, and we uploaded all the data successfully.&lt;/p&gt;

&lt;p&gt;But had I not have The Hunch&lt;span&gt;™&lt;/span&gt;, had I not asked the question, we would have uploaded the bad data, and we would have learnt about it much, much later.&lt;/p&gt;

&lt;h2&gt;Square Miles Conversion&lt;/h2&gt;

&lt;p&gt;I &lt;a href="http://smartpuffin.com/little-geo-stories-square-miles"&gt;saw a feature on our website&lt;/a&gt;, where some geo-math was involved.&lt;i&gt; I immediately had The Hunch&lt;/i&gt;&lt;span&gt;&lt;i&gt;™&lt;/i&gt;&lt;/span&gt;: there must be a bug.&lt;/p&gt;

&lt;p&gt;It turned out to be correct, there was a funny bug which was live on our website for 10 years, without anyone noticing.&lt;/p&gt;

&lt;h2&gt;New API idea&lt;/h2&gt;

&lt;p&gt;Our team was rebuilding a product. The original product was built some 15 years ago, and evolved chaotically.&lt;/p&gt;

&lt;p&gt;My colleagues were in love with a particular idea. The new API was supposed to distinguish between 3 use cases that were the same in the old product.&lt;/p&gt;

&lt;p&gt;I was very new to the team, and I wasn't completely sold on the idea. I felt like I didn't understand it enough. I thought it might be too complex for the end users. I estimated that a lot of work was needed to support the split, including categorizing the existing data and supporting backwards compatibility. In short, my first days in the new team were full of &lt;i&gt;The Hunch&lt;/i&gt;&lt;span&gt;&lt;i&gt;™&lt;/i&gt;&lt;/span&gt;.&lt;/p&gt;

&lt;p&gt;But I decided that my colleagues, knowing the domain area better than me, have thought about all this. I assumed they estimated the amount of work and agreed with it - before I joined them.&lt;/p&gt;

&lt;p&gt;They assured me that yes, some work is needed to categorise the existing data into these 3 use cases, but it is rather straightforward. A person from my team will do that, and will ask 2 more data specialists for help. The results will be ready very soon. And meanwhile, why don't we go ahead with the implementation?&lt;/p&gt;

&lt;p&gt;I voiced my concerns, but started to implement the new API.&lt;/p&gt;

&lt;p&gt;A week after, we met to see how the data split was going.&lt;/p&gt;

&lt;p&gt;All 3 data specialists who were categorizing the data disagreed on every single data entry.&lt;/p&gt;

&lt;p&gt;I asked them some questions, and it became clear that they understood the use cases differently. Moreover, all my own team members - including myself - understood it differently as well.&lt;/p&gt;

&lt;p&gt;Setting what's happening, my team members agreed to postpone the feature until there is more clarity on the use cases.&lt;/p&gt;

&lt;p&gt;Had I not seen that the use cases and not thought through enough, we would have offered a half-baked product to our users, and we wouldn't be able to explain the reason to split the use cases to them.&lt;/p&gt;

&lt;h2&gt;Collaboration between two teams&lt;/h2&gt;

&lt;p&gt;I supervised implementing a cross-team task.&lt;/p&gt;

&lt;p&gt;The problem was that many places used different APIs to fetch the same data. The APIs worked slightly differently and returned different results. The users saw different values and complained.&lt;/p&gt;

&lt;p&gt;The task was to clean it all up. The purpose of the task was to:&lt;/p&gt;

&lt;ol&gt;
    &lt;li&gt;Use one single API in all places, because:&lt;/li&gt;
    &lt;li&gt;We wanted to unify display.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Developer1 implemented new API calls in three places. For some reason, in two of them they overrided results and displayed something different based on some condition.&lt;/p&gt;

&lt;p&gt;So we still had the same inconsistency as before. This solution sort of complies with purpose 1), but completely defeats 2).&lt;/p&gt;

&lt;p&gt;Developer2 replaced the API call in one place that I pointed out as an example. Turned out, results were overrided further in the code, based on yet &lt;i&gt;another&lt;/i&gt; condition.&lt;/p&gt;

&lt;p&gt;Moreover, in the area of responsibility of Developer2 there was one more place with the old API. They didn't notice it and didn't make any changes to that place.&lt;/p&gt;

&lt;p&gt;Again, this solution half-complies with 1), but is out of line with 2).&lt;/p&gt;

&lt;p&gt;I found out about all this only when I replaced the API call in yet another place. While pushing my code, I felt &lt;i&gt;The Hunch&lt;/i&gt;&lt;span&gt;&lt;i&gt;™&lt;/i&gt;&lt;/span&gt;. Because the task was so complex and distributed between several people, I decided to test all changes at once.&lt;/p&gt;

&lt;p&gt;What I saw was that &lt;i&gt;all&lt;/i&gt; of them were different from each other.&lt;/p&gt;

&lt;p&gt;After all these efforts, customers were still confused by different data on different pages. The developers' time was spent twice. And again, it would have been noticed much later, had I not decided to double check.&lt;/p&gt;

&lt;h2&gt;When I failed&lt;/h2&gt;

&lt;p&gt;Long time ago, we were &lt;a href="http://smartpuffin.com/gis-system-our-requirements/"&gt;implementing a new GIS-system&lt;/a&gt;. Our old system was storing coordinates in the UTM-projection, which meant you can work with only a relatively small piece of map at a time.&lt;/p&gt;

&lt;p&gt;In the new system, we wanted to have the map of the whole world.&lt;/p&gt;

&lt;p&gt;We made a decision quickly: let's store coordinates in latitude and longitude, and always work with them like that. When we want to display them on the screen, we will project them as needed.&lt;/p&gt;

&lt;p&gt;Our next decision was to split the map to &lt;a href="http://smartpuffin.com/gis-system-map-navigation/"&gt;tiles&lt;/a&gt; to display them on the screen. And here we also made the decision to use latitude+longitude. It seemed only logical.&lt;/p&gt;

&lt;p&gt;I spent almost a month implementing the tiles on latitude+longitude coordinates. Doing math on the sphere is hard, and I made a lot of mistakes. It was taking forever. I just didn't seem to get it right.&lt;/p&gt;

&lt;p&gt;Seeing how I struggle, a more senior developer proposed to scratch all that and make a decision to have tiles in flat projected coordinates, using the projection our customers were using the most.&lt;/p&gt;

&lt;p&gt;I agreed reluctantly, since I still thought having "real" spherical coordinates was "right". I deleted the complex code and wrote the new one in just 3 days. It's been working perfectly ever since.&lt;/p&gt;

&lt;p&gt;I didn't have &lt;i&gt;The Hunch&lt;/i&gt;&lt;span&gt;&lt;i&gt;™&lt;/i&gt;&lt;/span&gt; back then - and, as you can see, the team lost a month because I didn't think very well about the consequences of the decision - how complex the math would be to implement.&lt;/p&gt;

&lt;h2&gt;How to do it yourself&lt;/h2&gt;

&lt;p&gt;I see many people not thinking through all aspects of their tasks and decisions, from technical to product ones, to business ones, to data collection ones.&lt;/p&gt;

&lt;p&gt;A task, even small and simple one, often involves much more than it seems. For developers, I wrote an article &lt;a href="https://dev.to/ice_lenor/problem-solving-thinking-about-corner-cases-47hh"&gt;helping them to think about corner cases&lt;/a&gt; in advance, when coding. The similar advice is applicable to all other sorts of tasks.&lt;/p&gt;

&lt;p&gt;Try to think about the problem &lt;strong&gt;from all angles&lt;/strong&gt;. What other people it involves? Does it involve changing existing stuff, be it code or processes or data? Does it align smoothly with everything else? Is there a logical flaw?&lt;/p&gt;

&lt;p&gt;It is like testing. You list positive cases, negative cases, and corner cases; you also test other classes your change could touch; you ask your users for help; etc.&lt;/p&gt;

&lt;p&gt;It will almost definitely be &lt;strong&gt;cheaper and faster&lt;/strong&gt; to spend some time investigating first, than to rush into implementation and fail later.&lt;/p&gt;

&lt;p&gt;Knowing what is actually involved will help you with &lt;strong&gt;prioritization&lt;/strong&gt;. If the task is large, you might decide to do a smaller one instead.&lt;/p&gt;

&lt;p&gt;Sometimes, after looking at all aspects, you might make a decision to do the task &lt;i&gt;with&lt;/i&gt; the flaw. You might decide to not care about a certain problem or make a trade-off. Still, you will make an informed decision, and not simply go with the flow.&lt;/p&gt;

</description>
      <category>problemsolving</category>
      <category>analysis</category>
    </item>
    <item>
      <title>C++ From The Past - I found C++ and OOP lectures I wrote back in 2008!</title>
      <dc:creator>Elena</dc:creator>
      <pubDate>Wed, 04 Jul 2018 21:57:00 +0000</pubDate>
      <link>https://dev.to/ice_lenor/c-from-the-past---i-found-c-and-oop-lectures-i-wrote-back-from-2008-3h3a</link>
      <guid>https://dev.to/ice_lenor/c-from-the-past---i-found-c-and-oop-lectures-i-wrote-back-from-2008-3h3a</guid>
      <description>&lt;p&gt;You can't possibly imagine what I found today! 😍&lt;br&gt;
Back in 2008 I wrote a set of lectures on C++ and OOP for my uni, and never published them anywhere. Until today.&lt;/p&gt;

&lt;p&gt;It's pure gold. 60 pages, so very detailed, with code samples and full source code files. It goes about incapculation, inheritance, polymorphism, const modifier (all these lovely &lt;em&gt;int const * const&lt;/em&gt;), exceptions, memory management, reinterpret_cast's! Pointers vs references! Templates!! Auto_ptr's! Unicode support!! I was so smart :).&lt;/p&gt;

&lt;p&gt;&lt;a href="https://docs.google.com/document/d/15nlDYJfeR5O7IvMWQKwXl091Ep6zq09O8V583m98cFQ/edit?usp=sharing"&gt;Here is the link&lt;/a&gt;. It is all in Russian. Enjoy! :)&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;UPD&lt;/strong&gt;: in August 2019 I have learned that the lectures are still in use in my uni! They don't credit me,  unfortunately, but i am still happy the lectures are useful to this day, 11 years later.&lt;/p&gt;




&lt;p&gt;Okay, okay, why did I write any lectures at all? I wasn't a professor or a teacher, I was just a 2-year nerdy student, very much a C++ fan.&lt;/p&gt;

&lt;h3&gt;Why I wrote OOP lectures&lt;/h3&gt;

&lt;p&gt;When the OOP course started, in my second year of the university, I was so excited. I already knew what it was, but hoped to learn so much more.&lt;/p&gt;

&lt;p&gt;I found all lectures before the start of the semester, and read them.&lt;/p&gt;

&lt;p&gt;First lecture went: let's have a class to describe a &lt;em&gt;point&lt;/em&gt;. It looked like this:&lt;/p&gt;

&lt;pre&gt;class Point {
public:
  int x;
  int y;
}&lt;/pre&gt;

&lt;p&gt;Second lecture described a &lt;em&gt;line&lt;/em&gt;. The line was inherited from the point class and had two extra fields: x2 and y2.&lt;/p&gt;

&lt;pre&gt;class Line: public Point {
public:
  int x2;
  int y2;
}&lt;/pre&gt;

&lt;p&gt;I went: wait, whaaaat?..&lt;/p&gt;

&lt;p&gt;Third lecture described a &lt;em&gt;square&lt;/em&gt;, inherited from the line class, with four more fields: x3, y3, x4, y4.&lt;/p&gt;

&lt;p&gt;At that point I started to suspect it was some sort of proof by contradiction. It wasn't. The lectures went on.&lt;/p&gt;

&lt;p&gt;I went and talked with the professor. I told her it wasn't the best approach, and explained why. I offered to write new lectures for her, instead of homework. She said rather indifferently: yea, go for it. Why not.&lt;/p&gt;

&lt;p&gt;That autumn semester in 2008 I wrote my own OOP lectures. I was so happy writing! I enjoyed the process, the result, and how I get to summarize my thoughts in a neat way.&lt;/p&gt;

&lt;p&gt;To my classmates my lectures seemed to help much more than the original ones. That was a nice feeling too. I was helping!&lt;/p&gt;

&lt;p&gt;In the end of the semester, I sent the finished lectures to the professor, got my A, and never heard back from her. I don't know if she credited me. I don't even know if she used them at all. I found my first job right after these lectures, and didn't have time to follow up.&lt;/p&gt;

&lt;p&gt;I do hope she found them useful.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;UPD&lt;/strong&gt;: in August 2019 I have learned that the lectures are still in use in my uni! They don't credit me,  unfortunately, but i am still happy the lectures are useful to this day, 11 years later.&lt;/p&gt;




&lt;p&gt;But how come I never published them anywhere else?&lt;/p&gt;

&lt;h3&gt;How toxic community discouraged me from publishing&lt;/h3&gt;

&lt;p&gt;While still in progress, I posted the lectures anonymously on a Russian developers' forum and asked for feedback. Some developers answered and offered a couple of tips, but others asked why am I doing this: am I going to sleep with the professor? Is she young and beautiful? If not, why do I even bother?&lt;/p&gt;

&lt;p&gt;When they discovered I am a woman too, the discussion went off on a tangent. They started discussing me instead, and how I possibly couldn't exist. Women can't code, everyone knows that. I must have pretended to be a woman to draw attention to my weak lectures. Laughable, really. Or was I ugly?&lt;/p&gt;

&lt;p&gt;This was when I decided I don't want to post anything anymore.&lt;/p&gt;

&lt;p&gt;It took me several (7? 8?) years to be not afraid to share my professional insights publicly. That's why I didn't have a blog for many years, and didn't speak on conferences. I was afraid I will be laughed at again.&lt;/p&gt;

&lt;p&gt;Okay, my story about writing C++ lectures somehow turned into a sad story about toxic developers community. But hey, I overcame this, and I'm posing here now :).&lt;/p&gt;

&lt;h3&gt;Feeling sentimental&lt;/h3&gt;

&lt;p&gt;Why am I publishing the lectures now? It's been ten years, and they are hopelessly out of date. Since then, three new C++ standards were published. When I was writing them, the current standard was C++03, from 2003, and I thought the new standard will never ever be released.&lt;/p&gt;

&lt;p&gt;So why now, in 2018?&lt;/p&gt;

&lt;p&gt;Why, I am feeling sentimental, of course. And I don't want them to disappear. When I'm old and gray, I will be telling my grandchildren this story, while sitting in a rocking chair and drinking orange juice.&lt;/p&gt;

&lt;p&gt;There was a time, I'll say, when your grandma was young...&lt;/p&gt;

</description>
      <category>programming</category>
      <category>beginners</category>
      <category>longlongago</category>
      <category>mentalhealth</category>
    </item>
    <item>
      <title>Code Reviews Are Awesome, Here Are 7 Reasons Why</title>
      <dc:creator>Elena</dc:creator>
      <pubDate>Wed, 20 Jun 2018 22:04:39 +0000</pubDate>
      <link>https://dev.to/ice_lenor/code-reviews-are-awesome-here-are-7-reasons-why-54oi</link>
      <guid>https://dev.to/ice_lenor/code-reviews-are-awesome-here-are-7-reasons-why-54oi</guid>
      <description>&lt;p&gt;&lt;i&gt;This post was originally published in my blog &lt;a href="http://smartpuffin.com/code-reviews-are-awesome-here-are-7-reasons-why/"&gt;smartpuffin.com&lt;/a&gt;.&lt;/i&gt;&lt;/p&gt;

&lt;p&gt;Code reviews are a great practice to apply in software development. The approach is very simple: when you're done with your code, give it to someone else to look at and leave comments.&lt;/p&gt;

&lt;p&gt;Despite of its simplicity, it brings considerable advantages. Here are 7 reasons why this practice is useful.&lt;/p&gt;

&lt;h3&gt;1. Finding bugs&lt;/h3&gt;

&lt;p&gt;Another developer, just by looking at your code, may find bugs or forgotten scenarios.&lt;/p&gt;

&lt;p&gt;No one writes perfect code all the time. A second pair of eyes is really helpful.&lt;/p&gt;

&lt;p&gt;Even quality assurance engineers can miss some obscure cases which can easily be spotted by looking at the code with fresh eyes.&lt;/p&gt;

&lt;h3&gt;2. Finding problems&lt;/h3&gt;

&lt;p&gt;You can spot cases when it is not strictly a bug, but something still can be improved. Think questions like this:&lt;/p&gt;

&lt;ul&gt;
    &lt;li&gt;"This is not exactly a bug, but do you think it would be better if we did X instead?"&lt;/li&gt;
    &lt;li&gt;"If there are too many elements, this method is going to be slow. How about we sort the items first and use the binary search? How about we use a hashmap, a heap, a graph, a set, a smart algorithm, an index on this field, a garbage collection trick?"&lt;/li&gt;
    &lt;li&gt;"Maybe we should normalize these tables and not duplicate this data?" (Or, perhaps, the other way around.)&lt;/li&gt;
    &lt;li&gt;"A test is missing for the situation N."&lt;/li&gt;
    &lt;li&gt;"When the user does X, the system behaves in way Y. But maybe users would prefer Z?"&lt;/li&gt;
    &lt;li&gt;"You implemented something that was missing from the specification, let's figure out what it should be."&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Here are &lt;a href="http://smartpuffin.com/problem-solving-thinking-about-corner-cases/"&gt;some tips about how to improve&lt;/a&gt; your thinking about corner cases.&lt;/p&gt;

&lt;h3&gt;3. Improving code quality&lt;/h3&gt;

&lt;p&gt;You might be using a static analysis tool, such as StyleCop for C#, Checkstyle for Java, or Lint for CSS. However, the tool cannot catch all problems.&lt;/p&gt;

&lt;p&gt;For example, a reviewer can give an advice about a class name, or how to split the logic between methods, or how to &lt;a href="http://smartpuffin.com/modularization-dependency-management/"&gt;separate responsibilities&lt;/a&gt; between modules or services.&lt;/p&gt;

&lt;p&gt;Overall, the reviewer should be able to read the code easily. After all, we &lt;a href="http://smartpuffin.com/design-for-readability/"&gt;read the code 10 times more often&lt;/a&gt; than we write it.&lt;/p&gt;

&lt;p&gt;A developer writing the code is so immersed into the context that they understand everything. However, after a couple of months all knowledge is lost, and your own code looks as unfamiliar as if someone else's. So making the code readable is for your own benefit.&lt;/p&gt;

&lt;p&gt;And what is the better way than, you know, ask someone to read it?&lt;/p&gt;

&lt;h3&gt;4. Testing&lt;/h3&gt;

&lt;p&gt;The reviewer runs your code to see if it's working, and how exactly. By doing that, they may find some bugs. This is great because it helps you to publish a better product, you get the feedback faster, and the load on the QA is reduced.&lt;/p&gt;

&lt;h3&gt;5. Educating junior developers&lt;/h3&gt;

&lt;p&gt;It would be a mistake to think that junior developers cannot or shouldn't review the code of more senior ones. They are very much able to find bugs or problems with code readability.&lt;/p&gt;

&lt;p&gt;But another important aspect is that they learn how to do things. By giving them your awesome code to review, you teach them on an example.&lt;/p&gt;

&lt;h3&gt;6. Sharing the knowledge&lt;/h3&gt;

&lt;p&gt;A team member, while reviewing someone else's code, learns about the part of the system which is being changed. They build a better understanding of the system as a whole.&lt;/p&gt;

&lt;p&gt;And next time they have to implement a feature in that area, they are prepared.&lt;/p&gt;

&lt;h3&gt;7. Building trust&lt;/h3&gt;

&lt;p&gt;I know this one sounds a bit strange. How am I supposed to trust the colleagues who are going to criticize me?!&lt;/p&gt;

&lt;p&gt;But hear me out. Code reviews, when everyone in the team is doing them equally, help the team members to feel like they are being trusted. It builds the sense of reciprocity. If you are asked to review someone's code, you feel like they respect you and your opinion. If you ask someone to review your code, you show that you value their input and are open to feedback and improvement.&lt;/p&gt;

&lt;p&gt;You need to make sure to criticize constructively and not attack or condescend. If someone says to you: "that's a &lt;a href="http://smartpuffin.com/refactoring-luxury-or-necessity/"&gt;horrible code&lt;/a&gt;", no trust is going to be built for sure. It is demotivating and simply annoying. You are not going to want to ask that person anymore.&lt;/p&gt;

&lt;p&gt;The feedback should be given in a kind and constructive way, and make sure (!) to always (!) explain the reasons. Absolutely do explain why you think it should be done in a different way. You found a bug? You found a problem? You cannot read it easily? Does it not play along with other parts of your system? Explain that.&lt;/p&gt;

&lt;p&gt;If you can give a constructive advice about how to do it better, that's the best.&lt;/p&gt;




&lt;p&gt;Do you do code reviews? What does the process look like? What advantages do they have for your team? Please share with me, I'd love to know!&lt;/p&gt;

</description>
      <category>code</category>
      <category>codereview</category>
      <category>codereviews</category>
      <category>codequality</category>
    </item>
  </channel>
</rss>
