Nyt-flutter-clean-architecture-unit-test - Simple Flutter project built based on BLoC and Clean architecture with both Unit and integration tests

Overview

Table of Content

News Reader

News Reader is simple flutter app to hit the NY Times Most Popular Articles API and show a list of articles, that shows details when items on the list are tapped (a typical master/detail app).

We'll be using the most viewed section of this API.

http://api.nytimes.com/svc/mostpopular/v2/mostviewed/{section}/{period}.json?api-key=sample-key To test this API, you can use all-sections for the section path component in the URL above and 7 for period (available period values are 1, 7 and 30, which represents how far back, in days, the API returns results for).

http://api.nytimes.com/svc/mostpopular/v2/mostviewed/all-sections/7.json?api-key=sample-key

alt text

Requirements

  • Android Studio
  • Flutter SDK 2.8.1

API Key

An API key is necessary to successfully connect to the API that the app uses. Once an API key has been aquired, change the API_KEY property in /nyt_flutter/lib/common/contant.dart and run the app.

App Architecture

This sample follows BLoC pattern + Clean Architecture.

Model/Entities

The model is the domain object. It represents the actual data and/or information we are dealing with. An example of a model might be a contact (containing name, phone number, address, etc) or the characteristics of a live streaming publishing point.

The key to remember with the model is that it holds the information, but not behaviors or services that manipulate the information. It is not responsible for formatting text to look pretty on the screen, or fetching a list of items from a remote server (in fact, in that list, each item would most likely be a model of its own). Business logic is typically kept separate from the model, and encapsulated in other classes that act on the model.

Data layer

Provides all required data to the repository in form of models/entities.

Remote data source

Manage all server/external API calls.

Local data source

Manage all local data storage: example SQLite implementation, Room, Realm...

Repository

The decision maker class when it comes to manage data CRUD operations. Operations can be done in this layer is caching mechanism, manage consecutive api calls etc...

Usecases/Interactors

Represents concepts of the business, information about the current situation and business rules.

BLoC

There are three primary gadgets in the BLoC library:

  • Bloc
  • BlocBuilder
  • BlocProvider You’ll require them to set up BLoCs, construct those BLoCs as indicated by the progressions in the app’s state, and set up conditions. How about we perceive how to execute every gadget and use it in your app’s business rationale.
Bloc

The Bloc gadget is the fundamental segment you’ll have to execute all business rationale. To utilize it, expand the Bloc class and supersede the mapEventToState and initialState techniques.

BlocBuilder

BlocBuilder is a gadget that reacts to new states by building BLoCs. This gadget can be called on numerous occasions and acts like a capacity that reacts to changes in the state by making gadgets that appear new UI components.

BlocProvider

This gadget fills in as a reliance infusion, which means it can give BLoCs to a few gadgets all at once that have a place with the equivalent subtree. BlocProvider is utilized to construct blocs that will be accessible for all gadgets in the subtree.

Getting Started

This repository implements the following quality gates:

Build Pipeline

  • Static code checks: running lint to check the code for any issues.
  • Unit testing: running the unit tests
  • Code coverage: generating code coverage reports using the LCOV
  • Integration testing: running the functional tests using Flutter Integration Testing

These steps can be run manually or using a Continous Integration tool such as Bitrise.

Checkout the Code

Checkout and run the code

git clone https://github.com/oudaykhaled/nyt-flutter-clean-architecture-unit-test.git

Major Libraries / Tools

Category Library/Tool Link
Development Flutter - Dart https://flutter.dev/
IDE Android Studio https://developer.android.com/studio
Unit Testing Flutter Unit Test https://docs.flutter.dev/cookbook/testing/unit/introduction
Code Coverage LCOV https://github.com/linux-test-project/lcov
Static Code Check Lint for Dart/Flutter https://pub.dev/packages/lint
Integration Testing Flutter Integration Testing https://docs.flutter.dev/cookbook/testing/integration/introduction
CI/CD Bitrise https://app.bitrise.io/
Dependency Injection injectable https://pub.dev/packages/injectable
Service Locator get_it https://pub.dev/packages/get_it
Presentation Layer Mangement flutter_bloc https://pub.dev/packages/flutter_bloc
Network Layer Mangement retrofit https://pub.dev/packages/retrofit
Code Generator Freezed https://pub.dev/packages/freezed
HTTP Client Dio https://pub.dev/packages/dio
Image Caching cached_network_image https://pub.dev/packages/cached_network_image
Mock Library Mockito https://pub.dev/packages/mockito

Setting up Prerequisites

Install LCOV

Run the following command in terminal sudo apt-get install lcov

Install scrcpy

Run the following command in terminal sudo apt install scrcpy

Generate files

Run the following command in terminal flutter pub run build_runner watch --delete-conflicting-outputs

Running Quality Gates and Deployment Commands

Linting

Run the following command in terminal flutter analyze alt text

Testing

Tests in Flutter are separated into 2 types:

Tests

Located at /test - These are tests that run on your machine. Use these tests to minimize execution time when your tests have no flutter framework dependencies or when you can mock the flutter framework dependencies. alt text

Integration tests

Located at /integration_test - These are tests that run on a hardware device or emulator. These tests have access to all flutter APIs, give you access to information such as the Context of the app you are testing, and let you control the app under test from your test code. Use these tests when writing integration and functional UI tests to automate user interaction, or when your tests have flutter dependencies that mock objects cannot satisfy. alt text alt text

Running the Unit Tests

Unit testing for Flutter applications is fully explained in the Flutter documentation. In this repository, From Android Studio

  • Right Clicking on the Class and select "Run
  • To see the coverage we have t the select "Run with Coverage"

Test Coverage

The test coverage uses the LCOV library In order to run both test and integration_test and generate a code coverage report, create a script file to do the job.

  
red=$(tput setaf 1)  
none=$(tput sgr0)  
filename=  
open_browser=  
  
show_help() {  
    printf "  
Script for running all unit and widget tests with code coverage.  
(run it from your root Flutter's project)  
*Important: requires lcov  
     Usage:   
 $0 [--help] [--open] [--filename <path>]where:  
 -o, --open Open the coverage in your browser, Default is google-chrome you can change this in the function open_cov(). -h, --help print this message -f <path>, --filename <path> Run a particular test file. For example:             -f test/a_particular_test.dart  
         Or you can run all tests in a directory  
 -f test/some_directory/"  
}  
  
run_tests() {  
    if [[ -f "pubspec.yaml" ]]; then  
  rm -f coverage/lcov.info  
        rm -f coverage/lcov-final.info  
        flutter test --coverage "$filename"  
  ch_dir  
  else  
  printf "\n${red}Error: this is not a Flutter project${none}\n"  
  exit 1  
  fi  
}  
  
run_report() {  
    if [[ -f "coverage/lcov.info" ]]; then  
  lcov -r coverage/lcov.info lib/resources/l10n/\* lib/\*/fake_\*.dart \  
             -o coverage/lcov-final.info  
        genhtml -o coverage coverage/lcov-final.info  
    else  
  printf "\n${red}Error: no coverage info was generated${none}\n"  
  exit 1  
  fi  
}  
  
ch_dir(){  
    dir=$(pwd)  
  input="$dir/coverage/lcov.info"  
  output="$dir/coverage/lcov_new.info"  
  echo "$input"  
  while read line  
    do  
  secondString="SF:$dir/"  
  echo "${line/SF:/$secondString}" >> $output  
    done < "$input"  
  
  mv $output $input  
}  
  
open_cov(){  
    # This depends on your system   
    # Google Chrome:  
 # google-chrome coverage/index-sort-l.html # Mozilla:  firefox coverage/index-sort-l.html  
}  
  
while [ "$1" != "" ]; do  
 case $1 in  
  -h|--help)  
            show_help  
 exit  ;;  
  -o|--open)  
            open_browser=1  
  ;;  
  -f|--filename)  
            shift  
  filename=$1  
            ;;  
  *)  
            show_help  
 exit  ;;  
 esac  shift  
done  
  
run_tests  
remove_from_coverage -f coverage/lcov.info -r '.g.dart$'  
remove_from_coverage -f coverage/lcov.info -r '.freezed.dart$'  
remove_from_coverage -f coverage/lcov.info -r '.config.dart$'  
run_report  
if [ "$open_browser" = "1" ]; then  
  open_cov  
fi

Below lines are added to ignore the generated files when generating the code coverage report:

remove_from_coverage -f coverage/lcov.info -r '.g.dart$'  
remove_from_coverage -f coverage/lcov.info -r '.freezed.dart$'  
remove_from_coverage -f coverage/lcov.info -r '.config.dart$' 

From the commandline

sh test_with_coverage.sh

Test coverage results are available at

/coverage/index.html alt text

CI-CD - Build via Bitrise (yml file)

This repo contains a bitrise, which is used to define a Bitrise declarative pipeline for CI-CD to build the code, run the quality gates, code coverage, static analysis and deploy to Bitrise.

Here is the structure of the bitrise declarative pipeline:

---  
format_version: '11'  
default_step_lib_source: 'https://github.com/bitrise-io/bitrise-steplib.git'  
project_type: flutter  
trigger_map:  
- push_branch: '*'  
  workflow: primary  
- pull_request_source_branch: '*'  
  workflow: primary  
workflows:  
  deploy:  
    steps:  
    - activate-ssh-key@4:  
        run_if: '{{getenv "SSH_RSA_PRIVATE_KEY" | ne ""}}'  
  - git-clone@6: {}  
    - script@1:  
        title: Do anything with Script step  
    - certificate-and-profile-installer@1: {}  
    - flutter-installer@0:  
        inputs:  
        - is_update: 'false'  
  - cache-pull@2: {}  
    - flutter-analyze@0:  
        inputs:  
        - project_location: $BITRISE_FLUTTER_PROJECT_LOCATION  
    - flutter-test@1:  
        inputs:  
        - project_location: $BITRISE_FLUTTER_PROJECT_LOCATION  
    - flutter-build@0:  
        inputs:  
        - project_location: $BITRISE_FLUTTER_PROJECT_LOCATION  
        - platform: both  
    - xcode-archive@4:  
        inputs:  
        - project_path: $BITRISE_PROJECT_PATH  
        - scheme: $BITRISE_SCHEME  
        - distribution_method: $BITRISE_DISTRIBUTION_METHOD  
        - configuration: Release  
    - deploy-to-bitrise-io@2: {}  
    - cache-push@2: {}  
  primary:  
    steps:  
    - activate-ssh-key@4:  
        run_if: '{{getenv "SSH_RSA_PRIVATE_KEY" | ne ""}}'  
  - git-clone@6: {}  
    - script@1:  
        title: Do anything with Script step  
    - flutter-installer@0:  
        inputs:  
        - is_update: 'false'  
  - cache-pull@2: {}  
    - [email protected]:  
        inputs:  
        - project_location: $BITRISE_FLUTTER_PROJECT_LOCATION  
    - flutter-test@1:  
        inputs:  
        - project_location: $BITRISE_FLUTTER_PROJECT_LOCATION  
    - deploy-to-bitrise-io@2: {}  
    - cache-push@2: {}  
meta:  
  bitrise.io:  
    stack: linux-docker-android-20.04  
    machine_type_id: elite  
app:  
  envs:  
  - opts:  
      is_expand: false  
    BITRISE_FLUTTER_PROJECT_LOCATION: .  
  - opts:  
      is_expand: false  
    BITRISE_PROJECT_PATH: .  
  - opts:  
      is_expand: false  
    BITRISE_SCHEME: .  
  - opts:  
      is_expand: false  
    BITRISE_DISTRIBUTION_METHOD: development

Below is an illustration of the pipeline that Bitrise will execute

alt text

Building the application using Bitrise

These steps should be followed to automated the app build using Bitrise:

  • Create an account on Bitrise.
  • Follow the wizard for creating a Flutter project on Bitrise.
  • In workflows tab, and select <>bitrise.yaml tab.
  • Choose Store in app repository to read the repository yaml file.

This repository already attached to a public bitrise project.

License

Apache License, Version 2.0

http://www.apache.org/licenses/LICENSE-2.0

You might also like...

FLutter Api Integration - Flutter Rest API Integration

FLutter Api Integration - Flutter Rest API Integration

Flutter_Rest_Api_integration Flutter_Rest_Api_integration. Preview How To Use To

Feb 17, 2022

Getx and Dio APi-Integration - Flutter RestApi Integration using Dio

Getx and Dio APi-Integration - Flutter RestApi Integration using Dio

Flutter RestApi Integration using Dio. Click this image to find videos== //Crud

Nov 5, 2022

clean architecture and clean code with flutter , with bloc and getx state managment .

example_bloc A new Flutter project. Getting Started This project is a starting point for a Flutter application. A few resources to get you started if

Aug 22, 2022

Proyect with Clean Architecture / Hexagonal Architecture - Patron BLoC - The MovieDB API

flutter_movies_db A new Flutter project. Getting Started This project is a starting point for a Flutter application. A few resources to get you starte

Sep 22, 2022

🎬 A movie catalog app for both Android & IOS ~ Flutter.io project in Dart | Dart, Bloc, Movies

Movie Catalog App 🎬 Browse through movies from the YIFY api Getting Started For help getting started with Flutter, view our online documentation. Tod

Nov 21, 2022

Flutter project to find and discover events with Clean Architecture and Bloc from SeatGeek API.

Flutter project to find and discover events with Clean Architecture and Bloc from SeatGeek API.

Dec 6, 2022

[Flutter SDK V.2] - Youtube Video is a Flutter application built to demonstrate the use of Modern development tools with best practices implementation like Clean Architecture, Modularization, Dependency Injection, BLoC, etc.

[Flutter SDK V.2] - Youtube Video is a Flutter application built to demonstrate the use of Modern development tools with best practices implementation like Clean Architecture, Modularization, Dependency Injection, BLoC, etc.

[Flutter SDK V.2] - Youtube Video is a Flutter application built to demonstrate the use of Modern development tools with best practices implementation like Clean Architecture, Modularization, Dependency Injection, BLoC, etc.

Jan 2, 2023

Flutterstarterproject - Clean Architecture Flutter starter project, using tdd + bloc

Flutterstarterproject - Clean Architecture Flutter starter project, using tdd + bloc

Flutter Starter Project Generated by the Nero Lab CLI 🤖 A Nero Lab Project crea

Dec 8, 2022
Owner
Ouday
Ouday
Integration test - Copy of the official Flutter integration test plugin

integration_test This package enables self-driving testing of Flutter code on de

null 0 Jan 5, 2022
The Integration Test Helper has pre-configured methods that allow for faster test deployment for end to end (e2e) test coverage.

The Integration Test Helper has pre-configured methods that allow for faster test deployment for end to end (e2e) test coverage (using Android and iOS

The Mobile Applications Community 2 Apr 7, 2022
🌈 Repository for a compass project, basically an App for displaying bank transfers, with API requests, Flag persistence, Infinite Scroll, Error Handling, Unit Tests, Extract Sharing working with SOLID, BLoC and Designer Patterns.

?? Green Bank Aplicação desenvolvida em Flutter com intuito de trabalhar conexão com API, Gerenciamento de estado usando BLoC, Refatoração, Arquitetur

André Guerra Santos 28 Oct 7, 2022
Flutter bloc cubit test knowdge - Flutter bloc cubit test knowdge

Flutter Bloc Simple Api This project is using weather api for featch data and di

Waruna Kaushalya 0 Jan 3, 2022
This project follows the Reso Coder course for flutter test-driven-development with clean architecture and BloC state management for a random trivia simple app.

This project follows the Reso Coder course for flutter test-driven-development with clean architecture and BloC state management for a random trivia simple app.

Tomas B Sarmiento Abella 1 Jan 5, 2022
Fake Firebase Performance for use during Flutter unit & widget tests.

Fake Firebase Performance Fakes to write unit tests for apps using Firebase Performance monitoring. Instantiate a FakeFirebasePerformance, then pass i

Philipp Bauer 2 Apr 16, 2022
Ozzie is your testing friend. Ozzie will take an screenshot during integration tests whenever you need. Ozzie will capture performance reports for you.

ozzie.flutter Ozzie is your testing friend. Ozzie will take an screenshot during integration tests whenever you need. Ozzie will capture performance r

Jorge Coca 40 Nov 3, 2022
Flutter-clean-architecture - A simple flutter project developed with TDD and using Clean Architecture principles.

Clean Architecture This is a study project to practice TDD and a good approach of Clean Architecture for flutter projects. It is based on Reso Coder s

Luiz Paulo Franz 8 Jul 21, 2022
Petrus Nguyễn Thái Học 193 Dec 29, 2022
Flutter-fb-integration - Flutter And firebase integration Guide

Quickstart Guide This project still use my firebase server config, if you want t

Naufal Aldy Pradana 0 Feb 2, 2022