Gordon  Murray

Gordon Murray

1669014960

How to Behavior-Driven Development with Django and Aloe

Imagine you are a Django developer building a social network for a lean startup. The CEO is pressuring your team for an MVP. The engineers have agreed to build the product using behavior-driven development (BDD) to deliver fast and efficient results. The product owner gives you the first feature request, and following the practice of all good programming methodologies, you begin the BDD process by writing a test. Next you code a bit of functionality to make your test pass and you consider your design. The last step requires you to analyze the feature itself. Does it belong in your app?

We can't answer that question for you, but we can teach you when to ask it. In the following tutorial, we walk you through the BDD development cycle by programming an example feature using Django and Aloe. Follow along to learn how you can use the BDD process to help catch and fix poor designs quickly while programming a stable app.

Objectives

By the time you complete this tutorial, you should be able to:

  1. Describe and practice behavior-driven development (BDD)
  2. Explain how to implement BDD in a new project
  3. Test your Django applications using Aloe

Project Setup

Want to build this project as you read the post?

Start by:

  1. Adding a project directory.
  2. Creating and activating a virtual environment.

Then, install the following dependencies and start a new Django project:

(venv)$ pip install \
        django==3.2.4 \
        djangorestframework==3.12.4 \
        aloe_django==0.2.0
(venv)$ django-admin startproject example_bdd .
(venv)$ python manage.py startapp example

You may need to manually install setuptools-scm (pip install setuptools-scm) if you get this error when trying to install aloe_django:

distutils.errors.DistutilsError: Could not find suitable distribution for Requirement.parse('setuptools_scm')

Update the INSTALLED_APPS list in settings.py:

INSTALLED_APPS = [

    ...

    'aloe_django',
    'rest_framework',
    'example',
]

Just looking for the code? Grab it from the repo.

Brief Overview of BDD

Behavior-driven development is a way of testing your code that challenges you to constantly revisit your design. When you write a test, you answer the question Does my code do what I expect it to do? through assertions. Failing tests expose the mistakes in your code. With BDD, you analyze a feature: Is the user experience what I expect it to be? There's nothing as concrete as a failing test to expose a bad feature, but the consequences of delivering a bad experience are tangible.

Execute BDD as part of your test development cycle. Draw the functional boundaries of a feature with tests. Create code that colors in the details. Step back and consider your design. And then do it all over again until the picture is complete.

Review the following post for a more in-depth explanation of BDD.

Your First Feature Request

"Users should be able to log into the app and see a list of their friends."

That's how your product manager starts the conversation about the app's first feature. It's not much but you can use it to write a test. She's actually requesting two pieces of functionality:

  1. user authentication
  2. the ability to form relationships between users.

Here's a rule of thumb: treat a conjunction like a beacon, warning you against trying to test too many things at once. If you ever see an "and" or an "or" in a test statement, you should break that test into smaller ones.

With that truism in mind take the first half of the feature request and write a test scenario: a user can log into the app. In order to support user authentication, your app must store user credentials and give users a way to access their data with those credentials. Here's how you translate those criteria into an Aloe .feature file.

example/features/friendships.feature

Feature: Friendships

  Scenario: A user can log into the app

    Given I empty the "User" table

    And I create the following users:
      | id | email             | username | password  |
      | 1  | annie@example.com | Annie    | pAssw0rd! |

    When I log in with username "Annie" and password "pAssw0rd!"

    Then I am logged in

An Aloe test case is called a feature. You program features using two files: a Feature file and a Steps file.

  1. The Feature file consists of statements written in plain English that describe how to configure, execute, and confirm the results of a test. Use the Feature keyword to label the feature and the Scenario keyword to define a user story that you are planning to test. In the example above, the scenario defines a series of steps that explain how to populate the User database table, log a user into the app, and validate the login. All step statements must begin with one of four keywords: Given, When, Then, or And.
  2. The Steps file contains Python functions that are mapped to the Feature file steps using regular expressions.

You may need to add an __init__.py file to the "features" directory for the interpreter to load the friendships_steps.py file correctly.

Run python manage.py harvest and see the following output.

nosetests --verbosity=1
Creating test database for alias 'default'...
E
======================================================================
ERROR: A user can log into the app (example.features.friendships: Friendships)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "django-aloe-bdd/venv/lib/python3.9/site-packages/aloe/registry.py", line 151, in wrapped
    return function(*args, **kwargs)
  File "django-aloe-bdd/example/features/friendships.feature", line 5, in A user can log into the app
    Given I empty the "User" table
  File "django-aloe-bdd/venv/lib/python3.9/site-packages/aloe/registry.py", line 151, in wrapped
    return function(*args, **kwargs)
  File "django-aloe-bdd/venv/lib/python3.9/site-packages/aloe/exceptions.py", line 44, in undefined_step
    raise NoDefinitionFound(step)
aloe.exceptions.NoDefinitionFound: The step r"Given I empty the "User" table" is not defined
-------------------- >> begin captured logging << --------------------
asyncio: DEBUG: Using selector: KqueueSelector
--------------------- >> end captured logging << ---------------------

----------------------------------------------------------------------
Ran 1 test in 0.506s

FAILED (errors=1)
Destroying test database for alias 'default'...

The test fails because you haven't mapped the step statements to Python functions. Do so in the following file.

example/features/friendships_steps.py

from aloe import before, step, world
from aloe.tools import guess_types
from aloe_django.steps.models import get_model
from django.contrib.auth.models import User
from rest_framework.test import APIClient


@before.each_feature
def before_each_feature(feature):
    world.client = APIClient()


@step('I empty the "([^"]+)" table')
def step_empty_table(self, model_name):
    get_model(model_name).objects.all().delete()


@step('I create the following users:')
def step_create_users(self):
    for user in guess_types(self.hashes):
        User.objects.create_user(**user)


@step('I log in with username "([^"]+)" and password "([^"]+)"')
def step_log_in(self, username, password):
    world.is_logged_in = world.client.login(username=username, password=password)


@step('I am logged in')
def step_confirm_log_in(self):
    assert world.is_logged_in

Each statement is mapped to a Python function via a @step() decorator. For example, Given I empty the "User" table will trigger the step_empty_table() function to run. In this case, the string "User" will be captured and passed to the function as the model_name parameter. The Aloe API includes a special global variable called world that can be used to store and retrieve data between test steps. Notice how the world.is_logged_in variable is created in step_log_in() and then accessed in step_confirm_log_in(). Aloe also defines a special @before decorator to execute functions before tests run.

One last thing: Consider the structure of the following statement:

And I create the following users:
  | id | email             | username | password  |
  | 1  | annie@example.com | Annie    | pAssw0rd! |

With Aloe, you can represent lists of dictionaries using a tabular structure. You can then access the data using self.hashes. Wrapping self.hashes in the guess_types() function returns the list with the dictionary values correctly typed. In the case of this example, guess_types(self.hashes) returns this code.

[{'id': 1, 'email': 'annie@example.com', 'username': 'Annie', 'password': 'pAssw0rd!'}]

Run the Aloe test suite with the following command and see all tests pass.

(venv)$ python manage.py harvest
nosetests --verbosity=1
Creating test database for alias 'default'...
.
----------------------------------------------------------------------
Ran 1 test in 0.512s

OK
Destroying test database for alias 'default'...

Write a test scenario for the second part of the feature request: a user can see a list of friends.

example/features/friendships.feature

Scenario: A user can see a list of friends

  Given I empty the "Friendship" table

  When I get a list of friends

  Then I see the following response data:
    | id | email | username |

Before you run the Aloe test suite, modify the first scenario to use the keyword Background instead of Scenario. Background is a special type of scenario that is run once before every block defined by Scenario in the Feature file. Every scenario needs to start with a clean slate and using Background refreshes the data every time it is run.

example/features/friendships.feature

Feature: Friendships

  Background: Set up common data

    Given I empty the "User" table

    And I create the following users:
      | id | email             | username | password  |
      | 1  | annie@example.com | Annie    | pAssw0rd! |
      | 2  | brian@example.com | Brian    | pAssw0rd! |
      | 3  | casey@example.com | Casey    | pAssw0rd! |

    When I log in with username "Annie" and password "pAssw0rd!"

    Then I am logged in

  Scenario: A user can see a list of friends

    Given I empty the "Friendship" table

    And I create the following friendships:
      | id | user1 | user2 |
      | 1  | 1     | 2     |

    # Annie and Brian are now friends.

    When I get a list of friends

    Then I see the following response data:
      | id | email             | username |
      | 2  | brian@example.com | Brian    |

Now that you're dealing with friendships between multiple users, add a couple new user records to the database to start. The new scenario clears all entries from a "Friendship" table and creates one new record to define a friendship between Annie and Brian. Then it calls an API to retrieve a list of Annie's friends and it confirms that the response data includes Brian.

The first step is to create a Friendship model. It's simple: It just links two users together.

example/models.py

from django.conf import settings
from django.db import models


class Friendship(models.Model):
    user1 = models.ForeignKey(
      settings.AUTH_USER_MODEL,
      on_delete=models.CASCADE,
      related_name='user1_friendships'
    )
    user2 = models.ForeignKey(
      settings.AUTH_USER_MODEL,
      on_delete=models.CASCADE,
      related_name='user2_friendships'
    )

Make a migration and run it.

(venv)$ python manage.py makemigrations
(venv)$ python manage.py migrate

Next, create a new test step for the I create the following friendships: statement.

example/features/friendships_steps.py

@step('I create the following friendships:')
def step_create_friendships(self):
    Friendship.objects.bulk_create([
        Friendship(
            id=data['id'],
            user1=User.objects.get(id=data['user1']),
            user2=User.objects.get(id=data['user2'])
        ) for data in guess_types(self.hashes)
    ])

Add the Friendship model import to the file.

from ..models import Friendship

Create an API to get a list of the logged-in user's friends. Create a serializer to handle the representation of the User resource.

example/serializers.py

from django.contrib.auth.models import User
from rest_framework import serializers


class UserSerializer(serializers.ModelSerializer):
    class Meta:
        model = User
        fields = ('id', 'email', 'username',)
        read_only_fields = fields

Create a manager to handle table-level functionality for your Friendship model.

example/models.py

# New import!
from django.db.models import Q


class FriendshipManager(models.Manager):
    def friends(self, user):
        """Get all users that are friends with the specified user."""
        # Get all friendships that involve the specified user.
        friendships = self.get_queryset().select_related(
            'user1', 'user2'
        ).filter(
            Q(user1=user) |
            Q(user2=user)
        )

        def other_user(friendship):
            if friendship.user1 == user:
                return friendship.user2
            return friendship.user1

        return map(other_user, friendships)

The friends() function retrieves all of the friendships that the specified user shares with other users. Then it returns a list of those other users. Add objects = FriendshipManager() to the Friendship model.

Create a simple ListAPIView to return a JSON-serialized list of your User resources.

example/views.py

from rest_framework.generics import ListAPIView

from .models import Friendship
from .serializers import UserSerializer


class FriendsView(ListAPIView):
    serializer_class = UserSerializer

    def get_queryset(self):
        return Friendship.objects.friends(self.request.user)

Finally, add a URL path.

example_bdd/urls.py

from django.urls import path

from example.views import FriendsView

urlpatterns = [
    path('friends/', FriendsView.as_view(), name='friends'),
]

Create the remaining Python step functions: One to call your new API and another generic function to confirm response payload data. (We can reuse this function to check any payload.)

example/features/friendships_steps.py

@step('I get a list of friends')
def step_get_friends(self):
    world.response = world.client.get('/friends/')


@step('I see the following response data:')
def step_confirm_response_data(self):
    response = world.response.json()
    if isinstance(response, list):
        assert guess_types(self.hashes) == response
    else:
        assert guess_types(self.hashes)[0] == response

Run the tests and watch them pass.

(venv)$ python manage.py harvest

Think of another test scenario. Users with no friends should see an empty list when they call the API.

example/features/friendships.feature

Scenario: A user with no friends sees an empty list

  Given I empty the "Friendship" table

  # Annie has no friends.

  When I get a list of friends

  Then I see the following response data:
    | id | email | username |

No new Python functions are required. You can reuse all of your steps! Tests pass without any intervention.

You need one last piece of functionality to get this feature off the ground. Users can get a list of their friends, but how do they make new friends? Here's a new scenario: "a user should be able to add another user as a friend." Users should be able to call an API to create a friendship with another user. You know the API works if a record gets created in the database.

example/features/friendships.feature

Scenario: A user can add a friend

  Given I empty the "Friendship" table

  When I add the following friendship:
    | user1 | user2 |
    | 1     | 2     |

  Then I see the following rows in the "Friendship" table:
    | user1 | user2 |
    | 1     | 2     |

Create the new step functions.

example/features/friendships_steps.py

@step('I add the following friendship:')
def step_add_friendship(self):
    world.response = world.client.post('/friendships/', data=guess_types(self.hashes[0]))


@step('I see the following rows in the "([^"]+)" table:')
def step_confirm_table(self, model_name):
    model_class = get_model(model_name)
    for data in guess_types(self.hashes):
        has_row = model_class.objects.filter(**data).exists()
        assert has_row

Extend the manager and do some refactoring.

example/models.py

class FriendshipManager(models.Manager):
    def friendships(self, user):
        """Get all friendships that involve the specified user."""
        return self.get_queryset().select_related(
            'user1', 'user2'
        ).filter(
            Q(user1=user) |
            Q(user2=user)
        )

    def friends(self, user):
        """Get all users that are friends with the specified user."""
        friendships = self.friendships(user)

        def other_user(friendship):
            if friendship.user1 == user:
                return friendship.user2
            return friendship.user1

        return map(other_user, friendships)

Add a new serializer to render the Friendship resources.

example/serializers.py

class FriendshipSerializer(serializers.ModelSerializer):
    class Meta:
        model = Friendship
        fields = ('id', 'user1', 'user2',)
        read_only_fields = ('id',)

Add a new view.

example/views.py

class FriendshipsView(ModelViewSet):
    serializer_class = FriendshipSerializer

    def get_queryset(self):
        return Friendship.objects.friendships(self.request.user)

Add a new URL.

example/urls.py

path('friendships/', FriendshipsView.as_view({'post': 'create'})),

Your code works and the tests pass!

Analyzing the Feature

Now that you've successfully programmed and tested your feature, it's time to analyze it. Two users become friends when one user adds the other one. This is not ideal behavior. Maybe the other user doesn't want to be friends -- don't they get a say? A user should request a friendship with another user, and the other user should be able to accept or reject that friendship.

Revise the scenario where a user adds another user as a friend: "a user should be able to request a friendship with another user."

Replace Scenario: A user can add a friend with this one.

example/features/friendships.feature

Scenario: A user can request a friendship with another user

  Given I empty the "Friendship" table

  When I request the following friendship:
    | user1 | user2 |
    | 1     | 2     |

  Then I see the following response data:
    | id | user1 | user2 | status  |
    | 3  | 1     | 2     | PENDING |

Refactor your test step to use a new API, /friendship-requests/.

example/features/friendships_steps.py

@step('I request the following friendship:')
def step_request_friendship(self):
    world.response = world.client.post('/friendship-requests/', data=guess_types(self.hashes[0]))

Start by adding a new status field to the Friendship model.

example/models.py

class Friendship(models.Model):
    PENDING = 'PENDING'
    ACCEPTED = 'ACCEPTED'
    REJECTED = 'REJECTED'
    STATUSES = (
      (PENDING, PENDING),
      (ACCEPTED, ACCEPTED),
      (REJECTED, REJECTED),
    )
    objects = FriendshipManager()
    user1 = models.ForeignKey(
      settings.AUTH_USER_MODEL,
      on_delete=models.CASCADE,
      related_name='user1_friendships'
    )
    user2 = models.ForeignKey(
      settings.AUTH_USER_MODEL,
      on_delete=models.CASCADE,
      related_name='user2_friendships'
    )
    status = models.CharField(max_length=8, choices=STATUSES, default=PENDING)

Friendships can be ACCEPTED or REJECTED. If the other user has not taken action, then the default status is PENDING.

Make a migration and migrate the database.

(venv)$ python manage.py makemigrations
(venv)$ python manage.py migrate

Rename the FriendshipsView to FriendshipRequestsView.

example/views.py

class FriendshipRequestsView(ModelViewSet):
    serializer_class = FriendshipSerializer

    def get_queryset(self):
        return Friendship.objects.friendships(self.request.user)

Replace the old URL path with the new one.

example/urls.py

path('friendship-requests/', FriendshipRequestsView.as_view({'post': 'create'}))

Add new test scenarios to test the accept and reject actions.

example/features/friendships.feature

Scenario: A user can accept a friendship request

  Given I empty the "Friendship" table

  And I create the following friendships:
    | id | user1 | user2 | status  |
    | 1  | 2     | 1     | PENDING |

  When I accept the friendship request with ID "1"

  Then I see the following response data:
    | id | user1 | user2 | status   |
    | 1  | 2     | 1     | ACCEPTED |

Scenario: A user can reject a friendship request

  Given I empty the "Friendship" table

  And I create the following friendships:
    | id | user1 | user2 | status  |
    | 1  | 2     | 1     | PENDING |

  When I reject the friendship request with ID "1"

  Then I see the following response data:
    | id | user1 | user2 | status   |
    | 1  | 2     | 1     | REJECTED |

Add new test steps.

example/features/friendships_steps.py

@step('I accept the friendship request with ID "([^"]+)"')
def step_accept_friendship_request(self, pk):
    world.response = world.client.put(f'/friendship-requests/{pk}/', data={
      'status': Friendship.ACCEPTED
    })


@step('I reject the friendship request with ID "([^"]+)"')
def step_reject_friendship_request(self, pk):
    world.response = world.client.put(f'/friendship-requests/{pk}/', data={
      'status': Friendship.REJECTED
    })

Add one more URL path. Users need to target the specific friendship they want to accept or reject.

example/urls.py

path('friendship-requests/<int:pk>/', FriendshipRequestsView.as_view({'put': 'partial_update'}))

Update Scenario: A user can see a list of friends to include the new status field.

example/features/friendships.feature

Scenario: A user can see a list of friends

  Given I empty the "Friendship" table

  And I create the following friendships:
    | id | user1 | user2 | status   |
    | 1  | 1     | 2     | ACCEPTED |

  # Annie and Brian are now friends.

  When I get a list of friends

  Then I see the following response data:
    | id | email             | username |
    | 2  | brian@example.com | Brian    |

Add one more scenario after Scenario: A user can see a list of friends to test filtering on the status. A user's friends consist of people who have accepted friendship requests from the user. Those who have not taken action or who have rejected the requests are not considered.

example/features/friendships.feature

Scenario: A user with no accepted friendship requests sees an empty list

  Given I empty the "Friendship" table

  And I create the following friendships:
    | id | user1 | user2 | status   |
    | 1  | 1     | 2     | PENDING  |
    | 2  | 1     | 3     | REJECTED |

  When I get a list of friends

  Then I see the following response data:
    | id | email | username |

Edit the step_create_friendships() function to implement the status field on the Friendship model.

example/features/friendships_steps.py

@step('I create the following friendships:')
def step_create_friendships(self):
    Friendship.objects.bulk_create([
        Friendship(
            id=data['id'],
            user1=User.objects.get(id=data['user1']),
            user2=User.objects.get(id=data['user2']),
            status=data['status']
        ) for data in guess_types(self.hashes)
    ])

And also edit the FriendshipSerializer serializer to implement the status field on the Friendship model.

example/serializers.py

class FriendshipSerializer(serializers.ModelSerializer):
    class Meta:
        model = Friendship
        fields = ('id', 'user1', 'user2', 'status',)
        read_only_fields = ('id',)

Complete the filtering by adjusting the friends() method on the manager.

example/models.py

def friends(self, user):
    """Get all users that are friends with the specified user."""
    friendships = self.friendships(user).filter(status=Friendship.ACCEPTED)

    def other_user(friendship):
        if friendship.user1 == user:
            return friendship.user2
        return friendship.user1

    return map(other_user, friendships)

Feature complete!

Conclusion

If you take one thing from this post, I hope it's this: Behavior-driven development is as much about feature analysis as it is about writing, testing, and designing code. Without that crucial step, you're not creating software, you're just programming. BDD is not the only way to produce software, but it's a good one. And if you're practicing BDD with a Django project, give Aloe a try.

Grab the code from the repo.

Original article source at: https://testdriven.io/

#django #developement 

What is GEEK

Buddha Community

How to Behavior-Driven Development with Django and Aloe
Marget D

Marget D

1626077187

4 key Features of Django Framework that Make it the Best Amongst all!

Django is one of the popular python based open-source web frameworks mainly used by the developers who like to have rapid development along with the clean pragmatic design.

Read this blog to know the various Django Features with details.

#django framework #django web development #django development company #django development services #python django development company #python django development

Ahebwe  Oscar

Ahebwe Oscar

1620177818

Django admin full Customization step by step

Welcome to my blog , hey everyone in this article you learn how to customize the Django app and view in the article you will know how to register  and unregister  models from the admin view how to add filtering how to add a custom input field, and a button that triggers an action on all objects and even how to change the look of your app and page using the Django suit package let’s get started.

Database

Custom Titles of Django Admin

Exclude in Django Admin

Fields in Django Admin

#django #create super user django #customize django admin dashboard #django admin #django admin custom field display #django admin customization #django admin full customization #django admin interface #django admin register all models #django customization

Shardul Bhatt

Shardul Bhatt

1616147643

Why should you use Django for Web Development?

Django is a highly powerful framework for building small and large scale web applications. Being a Python-based framework, Django for web development is the preferred choice of companies all over the world. 

If you are looking for proof of Django’s popularity, here it is - Django framework for web development is used by YouTube, Dropbox, Instagram, Pinterest, Google, Reddit, and many more. Being an open-source and maintainable web application development framework, companies adore it for building dynamic and sophisticated web applications. 

Now you must be asking yourself “is Django good for web development?” The framework has a lot of benefits over other frameworks like Ruby on Rails, Flutter, Xamarin, etc. When you want a robust, scalable and stable application with a large codebase, using Django for web development is the right choice. 

Read more: Pros and Cons of Django Web Framework for App Development

What are the advantages of using Django for web development?

Django is admired by web developers all over the world. It is an easy-to-use battery including a framework that doesn’t eat up a lot of time in configuration and setting up the development environment. 

The following benefits are your answer to  “why use Django for web development”:-

  1. Simplicity
    Django framework for web development is excellent because of its simplicity and the ease of use. It allows developers to do more than one iteration and make modifications without running the entire code from scratch.

    Apart from that, it makes development simpler with its Don’t Repeat Yourself Philosophy, allowing developers to reuse the codebase for creating different components.

  2. Ecosystem
    Django has a rich and diverse development ecosystem. It permits a lot of third-party apps and integrations. While setting up the ide for Django web development, you can use the third-party apps and integrations to add components or blocks in the web application.

    From authorization to sending emails, there are apps for some of the most common features. It reduces the time taken to write code for these programs and leads to the timely delivery of products.

  3. Documentation
    Django for web development comes with excellent documentation to develop real-world applications. While other frameworks have alphabetical lists and modules, Django provides quick references to developers for building applications from different stages in the process.

    The documentation is updated regularly as Python programmers add new exceptions, rules, and features to the open-source framework. While it is hard to keep it fine-tuned, it is one of the best documentation of a framework.

  4. Wide community
    If you are still asking what are the advantages of using Django for web development, then look at its wide community of developers. Django developers are increasing every day as the framework becomes a popular choice amongst enterprises to fulfill their web application needs.

    The community is ready to assist on all Python Django web development projects. There are regular meets, tutorials, and material that can help anyone working with Django. The community regularly answers queries, and you can find the solution to almost any Django problem.

  5. Libraries
    Django allows developers to use massive amounts of libraries for building feature-rich and functional applications. Django REST framework is an excellent library for building Application Programming Interfaces (APIs). Django CMS, Django-allauth, and many other libraries are used for adding functionalities to web applications.

    Since the framework uses Python, using libraries becomes an easy task. Python has a lot of libraries with Django integration that enables building quality applications.

Also Read: A Guide to Django Web Development for your Business

Start using Django for web application development

Whether you are looking for an ERP application or a B2C web app, Django framework for web development is the perfect solution. It allows you to develop scalable applications capable of handling heavy traffic load in the future.
You can hire Python developers and Django experts for Python development services from BoTree Technologies who can fulfill your web development needs.

Source: https://www.apsense.com/article/why-should-you-use-django-for-web-development.html

#python development services #django framework #django rest framework #django for web development #django for web development #django

Fredy  Larson

Fredy Larson

1595059664

How long does it take to develop/build an app?

With more of us using smartphones, the popularity of mobile applications has exploded. In the digital era, the number of people looking for products and services online is growing rapidly. Smartphone owners look for mobile applications that give them quick access to companies’ products and services. As a result, mobile apps provide customers with a lot of benefits in just one device.

Likewise, companies use mobile apps to increase customer loyalty and improve their services. Mobile Developers are in high demand as companies use apps not only to create brand awareness but also to gather information. For that reason, mobile apps are used as tools to collect valuable data from customers to help companies improve their offer.

There are many types of mobile applications, each with its own advantages. For example, native apps perform better, while web apps don’t need to be customized for the platform or operating system (OS). Likewise, hybrid apps provide users with comfortable user experience. However, you may be wondering how long it takes to develop an app.

To give you an idea of how long the app development process takes, here’s a short guide.

App Idea & Research

app-idea-research

_Average time spent: two to five weeks _

This is the initial stage and a crucial step in setting the project in the right direction. In this stage, you brainstorm ideas and select the best one. Apart from that, you’ll need to do some research to see if your idea is viable. Remember that coming up with an idea is easy; the hard part is to make it a reality.

All your ideas may seem viable, but you still have to run some tests to keep it as real as possible. For that reason, when Web Developers are building a web app, they analyze the available ideas to see which one is the best match for the targeted audience.

Targeting the right audience is crucial when you are developing an app. It saves time when shaping the app in the right direction as you have a clear set of objectives. Likewise, analyzing how the app affects the market is essential. During the research process, App Developers must gather information about potential competitors and threats. This helps the app owners develop strategies to tackle difficulties that come up after the launch.

The research process can take several weeks, but it determines how successful your app can be. For that reason, you must take your time to know all the weaknesses and strengths of the competitors, possible app strategies, and targeted audience.

The outcomes of this stage are app prototypes and the minimum feasible product.

#android app #frontend #ios app #minimum viable product (mvp) #mobile app development #web development #android app development #app development #app development for ios and android #app development process #ios and android app development #ios app development #stages in app development

Mitchel  Carter

Mitchel Carter

1602979200

Developer Career Path: To Become a Team Lead or Stay a Developer?

For a developer, becoming a team leader can be a trap or open up opportunities for creating software. Two years ago, when I was a developer, I was thinking, “I want to be a team leader. It’s so cool, he’s in charge of everything and gets more money. It’s the next step after a senior.” Back then, no one could tell me how wrong I was. I had to find it out myself.

I Got to Be a Team Leader — Twice

I’m naturally very organized. Whatever I do, I try to put things in order, create systems and processes. So I’ve always been inclined to take on more responsibilities than just coding. My first startup job, let’s call it T, was complete chaos in terms of development processes.

Now I probably wouldn’t work in a place like that, but at the time, I enjoyed the vibe. Just imagine it — numerous clients and a team leader who set tasks to the developers in person (and often privately). We would often miss deadlines and had to work late. Once, my boss called and asked me to come back to work at 8 p.m. to finish one feature — all because the deadline was “the next morning.” But at T, we were a family.

We also did everything ourselves — or at least tried to. I’ll never forget how I had to install Ubuntu on a rack server that we got from one of our investors. When I would turn it on, it sounded like a helicopter taking off!

At T, I became a CTO and managed a team of 10 people. So it was my first experience as a team leader.

Then I came to work at D — as a developer. And it was so different in every way when it came to processes.

They employed classic Scrum with sprints, burndown charts, demos, story points, planning, and backlog grooming. I was amazed by the quality of processes, but at first, I was just coding and minding my own business. Then I became friends with the Scrum master. I would ask him lots of questions, and he would willingly answer them and recommend good books.

My favorite was Scrum and XP from the Trenches by Henrik Kniberg. The process at D was based on its methods. As a result, both managers and sellers knew when to expect the result.

Then I joined Skyeng, also as a developer. Unlike my other jobs, it excels at continuous integration with features shipped every day. Within my team, we used a Kanban-like method.

We were also lucky to have our team leader, Petya. At our F2F meetings, we could discuss anything, from missing deadlines to setting up a task tracker. Sometimes I would just give feedback or he would give me advice.

That’s how Petya got to know I’d had some management experience at T and learned Scrum at D.

So one day, he offered me to host a stand-up.

#software-development #developer #dev-team-leadership #agile-software-development #web-development #mobile-app-development #ios-development #android-development