31,19 €
This book guides developers to create robust, production-ready C# 7 and .NET Core applications through the practice of test-driven development process.
In C# and .NET Core Test-Driven Development, you will learn the different stages of the TDD life cycle, basics of TDD, best practices, and anti-patterns. It will teach you how to create an ASP.NET Core MVC sample application, write testable code with SOLID principles and set up a dependency injection for your sample application. Next, you will learn the xUnit testing framework and learn how to use its attributes and assertions. You’ll see how to create data-driven unit tests and mock dependencies in your code. You will understand the difference between running and debugging your tests on .NET Core on LINUX versus Windows and Visual Studio. As you move forward, you will be able to create a healthy continuous integration process for your sample application using GitHub, TeamCity, Cake, and Microsoft VSTS.
By the end of this book, you will have learned how to write clean and robust code through the effective practice of TDD, set up CI build steps to test and build applications as well as how to package application for deployment on NuGet.
Das E-Book können Sie in Legimi-Apps oder einer beliebigen App lesen, die das folgende Format unterstützen:
Seitenzahl: 308
Veröffentlichungsjahr: 2018
Copyright © 2018 Packt Publishing
All rights reserved. No part of this book may be reproduced, stored in a retrieval system, or transmitted in any form or by any means, without the prior written permission of the publisher, except in the case of brief quotations embedded in critical articles or reviews.
Every effort has been made in the preparation of this book to ensure the accuracy of the information presented. However, the information contained in this book is sold without warranty, either express or implied. Neither the author, nor Packt Publishing or its dealers and distributors, will be held liable for any damages caused or alleged to have been caused directly or indirectly by this book.
Packt Publishing has endeavored to provide trademark information about all of the companies and products mentioned in this book by the appropriate use of capitals. However, Packt Publishing cannot guarantee the accuracy of this information.
Commissioning Editor: Merint MathewAcquisition Editor: Chaitanya NairContent Development Editor: Priyanka SawantTechnical Editor: Ruvika RaoCopy Editor: Safis EditingProject Coordinator: Vaidehi SawantProofreader: Safis EditingIndexer: Rekha NairGraphics: Jason MonteiroProduction Coordinator: Deepika Naik
First published: May 2018
Production reference: 1160518
Published by Packt Publishing Ltd. Livery Place 35 Livery Street Birmingham B3 2PB, UK.
ISBN 978-1-78829-248-1
www.packtpub.com
Mapt is an online digital library that gives you full access to over 5,000 books and videos, as well as industry leading tools to help you plan your personal development and advance your career. For more information, please visit our website.
Spend less time learning and more time coding with practical eBooks and Videos from over 4,000 industry professionals
Improve your learning with Skill Plans built especially for you
Get a free eBook or video every month
Mapt is fully searchable
Copy and paste, print, and bookmark content
Did you know that Packt offers eBook versions of every book published, with PDF and ePub files available? You can upgrade to the eBook version at www.PacktPub.com and as a print book customer, you are entitled to a discount on the eBook copy. Get in touch with us at [email protected] for more details.
At www.PacktPub.com, you can also read a collection of free technical articles, sign up for a range of free newsletters, and receive exclusive discounts and offers on Packt books and eBooks.
Ayobami Adewole comes from Ibadan city in Nigeria. He is very passionate about computers and what they can be programmed to do. He is an ardent lover of the .NET stack of technologies and has developed several cutting-edge enterprise applications using the platform.
He offers consultancy services on VoIP and Unified Communication technologies, Customer Relationship Management Systems, Business Process Automation, Enterprise Application Development, and Quality Assurance.
Gaurav Aroraa has an MPhil in computer science. He is a Microsoft MVP, lifetime member of Computer Society of India (CSI), advisory member of IndiaMentor, certified as a Scrum trainer/coach, XEN for ITIL-F, and APMG for PRINCE-F and PRINCE-P. He is an open source developer, contributor to TechNet Wiki, and the founder of Ovatic Systems Private Limited. During his 20 year career, he has mentored thousands of students and industry professionals. In addition to this, he's written 100+ white papers for research scholars and various universities across the globe.
If you're interested in becoming an author for Packt, please visit authors.packtpub.com and apply today. We have worked with thousands of developers and tech professionals, just like you, to help them share their insight with the global tech community. You can make a general application, apply for a specific hot topic that we are recruiting an author for, or submit your own idea.
Title Page
Copyright and Credits
C# and .NET Core Test-Driven Development
Dedication
Packt Upsell
Why subscribe?
PacktPub.com
Contributors
About the author
About the reviewer
Packt is searching for authors like you
Preface
Who this book is for
What this book covers
To get the most out of this book
Download the example code files
Download the color images
Conventions used
Get in touch
Reviews
Exploring Test-Driven Development
Difficulty in maintaining code
How does bad code appear?
Tight coupling
Code smell
Bad or broken designs
Naming the program elements
Source code readability
Poor source code documentation
Non-tested code
What we can do to prevent bad code
Loose coupling
Sound architecture and design
Preventing and detecting code smell
C# coding conventions
Succinct and proper documentation
Why test-driven development?
Building for longevity
The principles of test-driven development
Origin of TDD
TDD misconceptions
Benefits of TDD
Types of tests
Unit tests
Integration tests
System testing
User acceptance testing
Principles of TDD
Writing the tests
Writing the code
Running the tests
Refactoring
Doing TDD the wrong way
The TDD cycle
Summary
Getting Started with .NET Core
.NET Core framework
.NET Standard
.NET Core components
Supported languages
When to choose .NET Core over .NET Framework
Cross-platform requirements
Ease of deployment
Scalability and performance
Limitations of .NET Core
Structure of a .NET Core application
ASP.NET Core MVC project structure
wwwroot folder
Models, Views, and Controllers folders
JSON files – bower.json, appsettings.json, bundleconfig.json
Program.cs
Startup.cs
Tour of Microsoft's Visual Studio Code editor
Installing .NET Core on Linux
Installing and setting up Visual Studio Code on Linux
Exploring Visual Studio Code
A look at the new features of C# 7
Tuples enhancement
Out keyword
Ref locals and returns
Ref locals
Ref returns
Local function
Patterns matching
Digit separator and binary literal
Creating an ASP.NET MVC Core application
Summary
Writing Testable Code
Warning signs when writing untestable code
Tight coupling
Monster Constructor
Classes with more than one responsibility
Static objects
Law of Demeter
Train Wreck
The SOLID architecture principles
Single Responsibility Principle
Open-Closed Principle
Liskov Substitution Principle
Interface Segregation Principle
Dependency Inversion Principle
Setting up a DI container for ASP.NET Core MVC
Summary
.NET Core Unit Testing
The attributes of a good unit test
Readable
Unit independence
Repeatable
Maintainable and runs fast
Easy to set up, non-trivial, and with good coverage
Unit testing framework ecosystem for .NET Core and C#
.NET Core testing with MSTest
.NET Core testing with NUnit
xUnit.net
How to configure xUnit.net
xUnit.net test runners
Test parallelism
Unit testing consideration for ASP.NET MVC Core
Unit testing controllers
Unit testing razor pages
Structuring unit tests with xUnit
xUnit.net shared test context
Live unit testing with Visual Studio 2017 Enterprise
Proving unit test results with xUnit.net assertions
The test runners available on both .NET Core and Windows
ReSharper
Summary
Data-Driven Unit Tests
The benefits of data-driven unit testing
Tests brevity
Inclusive testing
xUnit.net theory attribute for creating data-driven tests
Inline data-driven unit tests
Property data-driven unit tests
MemberData attribute
ClassData attribute
Integrating data from other sources
SqlServerData attribute
Custom attribute
Summary
Mocking Dependencies
The benefits of mocking objects
Fast running tests
Dependencies isolation
Refactoring legacy code
Wider test coverage
The shortcomings of mocking frameworks
Interface explosion
Extra complexity
Mock explosion
Hand-rolling mocks versus using a mocking framework
Mocking concept
Benefits of hand-rolling mocks
Mocks and stubs
Hand-rolled mock
Mocking objects using Moq framework
Mocking methods, properties, and callback
Properties
Matching parameters
Events
Callbacks
Mock customization
CallBase
Mock repository
Implementing multiple interfaces in a mock
Verification method and property invocations with Moq
LINQ to mocks
Advanced Moq features
Mocking internal types
Summary
Continuous Integration and Project Hosting
Continuous integration
CI workflow
Single source code repository
Build automation
Automated tests
Identical test and production environments
Daily commit
Benefits of CI
Quick bugs detection
Improved productivity
Reduced risks
Facilitating continuous delivery
CI tools
Microsoft Team Foundation Server
TeamCity
Jenkins
Continuous delivery
Benefits of continuous delivery
Lower risks
Quality software products
Reduced costs
GitHub online project hosting
Project hosting
Branching with GitHub Flow
Pull request
Reviewing changes and merging
Basic Git commands
Configuration commands
Initializing repository commands
Change commands
Branching and merging commands
Configuring GitHub WebHooks
Consuming WebHooks
GitHub WebHook
Events and payloads
Setting up your first WebHook
TeamCity CI platform
TeamCity concepts
Installing TeamCity Server
TeamCity CI workflow
Configuring and running build
Summary
Creating Continuous Integration Build Processes
Installing the Cake Bootstrapper
Installation
PowerShell security
Cake Bootstrapper installation steps
Step 1
Step 2
Step 3
Writing build scripts in C#
Task
TaskSetup and TaskTeardown
Configuration and preprocessor directives
Dependencies
Criteria
Cake's error handling and finally block
LoanApplication build script
Cake Extension for Visual Studio
Cake templates
Task Runner Explorer
Syntax highlighting
Using Cake tasks to build steps
CI with Visual Studio Team Services
Setting up a project in VSTS
Installing Cake into VSTS
Adding a build task
Summary
Testing and Packaging the Application
Executing xUnit.net tests with Cake
Executing xUnit.net tests in .NET projects
Executing xUnit.net tests in .NET Core projects
.NET Core versioning
Versioning principle
Installer
Package manager
Docker
Semantic Versioning
.NET Core packages and metapackages
Metapackage
Microsoft.AspNetCore.All metapackage
Packaging for NuGet distribution
dotnet publish command
Creating a NuGet package
Summary
Other Books You May Enjoy
Leave a review - let other readers know what you think
How do you verify that your cross-platform .NET Core application will work wherever it is deployed? As your business, team, and the technical environment evolves, can your code evolve with it? You can simplify your code base, make finding and fixing bugs trivial, and ensure your code does what you think it does by following the principles of test-driven development.
This book guides developers through the process of creating robust, production-ready C# 7 and .NET Core applications by establishing a professional test-driven development process. To do this, you will begin by learning the stages of the TDD life cycle, some best practices, and some anti-patterns.
After covering the basics of TDD in the first chapter, you will get right into creating a sample ASP.NET Core MVC application. You will learn how to write testable code with SOLID principles, and set up dependency injection.
Next, you will learn how to create unit tests using the xUnit.net testing framework, and how to use its attributes and assertions. Once you have the basics in place, you will learn how to create data-driven unit tests and how to mock dependencies in your code.
At the end of this book, you will wrap up by creating a healthy continuous integration process, using GitHub, TeamCity, VSTS, and Cake. Finally, you will modify the Continuous Integration build to test, version, and package a sample application.
This book is for .NET developers who would like to build quality, flexible, easy-to-maintain, and efficient enterprise applications by implementing the principles of test-driven development.
Chapter 1, Exploring Test-Driven Development, introduces you to how you can improve your coding habits and code by learning and following the proven principles of test-driven development.
Chapter 2, Getting Started with .NET Core, introduces you to the super-cool new cross-platform capabilities of .NET Core and C# 7. You will learn by doing as we create an ASP.NET MVC application on Ubuntu Linux with test-driven development principles.
Chapter 3, Writing Testable Code, demonstrates that, in order to reap the benefits of a test-driven development cycle, you must write code that is testable. In this chapter, we will discuss the SOLID principles for creating testable code and learn how to set up our .NET core application for dependency injection.
Chapter 4, .NET Core Unit Testing, presents the unit testing frameworks available for .NET Core and C#. We will use the xUnit framework to create a shared test context of setup and teardown code. You will also understand how to create basic unit tests and prove the results of your unit tests with xUnit assertions.
Chapter 5, Data-Driven Unit Tests, presents concepts that allow you to test your code over a variety of inputs by running over a set of data, either inline or from a data source. In this chapter, we will create data-driven unit tests or theories in xUnit.
Chapter 6, Mocking Dependencies, explains that mock objects are simulated objects that mimic the behavior of real objects. In this chapter, you will learn how to use the Moq framework to isolate the class you're testing from its dependencies using mock objects created with Moq.
Chapter 7, Continuous Integration and Project Hosting, focuses on the goal of the test-driven development cycle of quickly providing feedback on code quality. A continuous integration process extends this feedback cycle to uncovering code integration issues. In this chapter, you will begin creating a continuous integration process that can provide rapid feedback on code quality and integration issues across a development team.
Chapter 8, Creating Continuous Integration Build Processes, explains that a great continuous integration process brings together many different steps into an easily repeatable process. In this chapter, you will configure TeamCity and VSTS to use a cross-platform build automation system called Cake to clean, build, restore package dependencies and test your solution.
Chapter 9, Testing and Packaging the Application, teaches you to modify the Cake build script to run your suite of xUnit tests. You will finish up the process by versioning and packaging an application for distribution on the various platforms that .NET Core supports.
C# programming and working knowledge of Microsoft Visual Studio is assumed.
You can download the example code files for this book from your account at www.packtpub.com. If you purchased this book elsewhere, you can visit www.packtpub.com/support and register to have the files emailed directly to you.
You can download the code files by following these steps:
Log in or register at
www.packtpub.com
.
Select the
SUPPORT
tab.
Click on
Code Downloads & Errata
.
Enter the name of the book in the
Search
box and follow the onscreen instructions.
Once the file is downloaded, please make sure that you unzip or extract the folder using the latest version of:
WinRAR/7-Zip for Windows
Zipeg/iZip/UnRarX for Mac
7-Zip/PeaZip for Linux
The code bundle for the book is also hosted on GitHub athttps://github.com/PacktPublishing/CSharp-and-.NET-Core-Test-Driven-Development. In case there's an update to the code, it will be updated on the existing GitHub repository.
We also have other code bundles from our rich catalog of books and videos available athttps://github.com/PacktPublishing/. Check them out!
We also provide a PDF file that has color images of the screenshots/diagrams used in this book. You can download it here: https://www.packtpub.com/sites/default/files/downloads/CSharpanddotNETTestDrivenDevelopment_ColorImages.pdf.
There are a number of text conventions used throughout this book.
CodeInText: Indicates code words in text, database table names, folder names, filenames, file extensions, pathnames, dummy URLs, user input, and Twitter handles. Here is an example: "For the test to pass, you have to implement the production code iteratively. When the following IsServerOnline method is implemented, the Test_IsServerOnline_ShouldReturnTrue test method is expected to pass."
A block of code is set as follows:
[Fact] public void Test_IsServerOnline_ShouldReturnTrue() { bool isOnline=IsServerOnline(); Assert.True(isOnline); }
Any command-line input or output is written as follows:
sudo apt-get update
sudo apt-get install dotnet-sdk-2.0.0
Bold: Indicates a new term, an important word, or words that you see onscreen. For example, words in menus or dialog boxes appear in the text like this. Here is an example: "Visual Studio Code will attempt to download the required dependencies for the Linux platform, Omnisharp for Linux and .NET Core Debugger."
Feedback from our readers is always welcome.
General feedback: Email [email protected] and mention the book title in the subject of your message. If you have questions about any aspect of this book, please email us at [email protected].
Errata: Although we have taken every care to ensure the accuracy of our content, mistakes do happen. If you have found a mistake in this book, we would be grateful if you would report this to us. Please visit www.packtpub.com/submit-errata, selecting your book, clicking on the Errata Submission Form link, and entering the details.
Piracy: If you come across any illegal copies of our works in any form on the Internet, we would be grateful if you would provide us with the location address or website name. Please contact us at [email protected] with a link to the material.
If you are interested in becoming an author: If there is a topic that you have expertise in and you are interested in either writing or contributing to a book, please visit authors.packtpub.com.
Please leave a review. Once you have read and used this book, why not leave a review on the site that you purchased it from? Potential readers can then see and use your unbiased opinion to make purchase decisions, we at Packt can understand what you think about our products, and our authors can see your feedback on their book. Thank you!
For more information about Packt, please visit packtpub.com.
In order to craft robust, maintainable, and scalable software applications, software development teams and stakeholders must make certain important decisions early in the software development process. These decision makers must adopt the software industry's tested and proven best practices and standards throughout the different stages of software development.
The quality of software projects can quickly degrade when developers build the code base using development approaches, coding styles, and practices that automatically make source code rigid and difficult to maintain. This chapter points out the habits and practices that result in writing bad code and should therefore be avoided. The programming habits, development styles, and approaches that should be learned to facilitate writing clean and maintainable code are explained.
In this chapter, we will cover the following topics:
Difficulty in maintaining code
How bad code gets that way
What we can do to prevent bad code
The principles of test-driven development
The test-driven development cycle
There are two types of code—good code and bad code. The syntax of both types of code may be correct when compiled and running the code can give the expected results. However, bad code leads to serious issues when it comes to extending or even making little changes to the code, due to the way it was written.
When programmers write code using unprofessional approaches and styles, this often results in bad code. Also, the use of unreadable coding styles or formats as well as not properly and effectively testing code are all precursors to bad code. Code can be written poorly when programmers sacrifice professionalism in order to meet approaching deadlines and project milestones.
I have come across a few software projects that rapidly become legacy software projects that are abandoned because of incessant production bugs and the inability to incorporate change requests from users easily. This is because these software applications were deployed into production with a severe accumulation of technical debts through bad code written by software developers as a result of making poor design and development decisions and using programming styles known to cause future maintenance problems.
Source code elements—methods, classes, comments, and other artifacts—should be easy to read, understand, debug, refactor, and extend if required by another developer other than the original developer; otherwise, bad code has already been written.
You know you have bad code when, extending or adding new features, you break the existing working features. This can also happen when there are portions of code that cannot be decoded or any changes to them will bring the system to a halt. Another reason for bad code is usually because of nonadherence to object-oriented and Don't Repeat Yourself (DRY) principles or wrong use of the principles.
Bad code doesn't just appear in a code base; programmers write bad code. Most of the time, bad code can be written because of any of the following reasons:
Use of wrong approaches by developers when writing code that is often attributed to tight coupling of components
Faulty program designs
Bad naming conventions for program elements and objects
Writing code that is not readable as well as having a code base without proper test cases, thus causing difficulty when there is a need to maintain the code base
Meaningful and descriptive element naming can greatly improve the source code's readability. It allows easy comprehension of the logical flow of the program. It is amazing how software developers still give names to program elements that are too short or not descriptive enough, such as giving a variable a letter name or using acronyms for variable naming.
Generic or elusive names for elements lead to ambiguity. For example, having a method name as Extract() or Calculate() at first glance results in subjective interpretations. The same is applicable to using vague names for variables. For example:
int x2;string xxya;
While program element naming in itself is an art, names are to be selected to define the purposes as well as succinctly describe the elements and ensure that the chosen names comply with the standards and rules of the programming language being used.
Code can be easily understood when written using the programming language's coding style and convention while avoiding the bad code pitfalls discussed earlier. However, source code documentation is very valuable and its importance in software projects cannot be overemphasized. Brief and meaningful documentation of classes and methods can give developers a quick insight into their internal structures and operations.
Understanding a complex or poorly written class becomes a nightmare when there is no proper documentation in place. When the original programmer that wrote the code is no longer around to provide clarifications, valuable productive time can be lost trying to understand how the class or method is implemented.
Though many articles have been written and discussions have been initiated at various developers' conferences on different types of testing—test-driven development, behavior-driven development, and acceptance test-driven development—it is very concerning that there are developers that continuously develop and ship software applications that are not thoroughly tested or tested at all.
Shipping applications that are poorly tested can have catastrophic consequences and maintenance problems. Notable is NASA's Mars Climate Orbiter launched on December 11, 1998 that failed just as the orbiter approached Mars, due to a software error caused by an error in conversion where the orbiter's program code was calculating a metric in pounds instead of newtons. A simple unit testing of the particular module responsible for calculating the metrics could have detected the error and maybe prevented the failure.
Also, according to the State of Test-First Methodologies 2016 Report, a survey of the adoption of test-first methodologies of more than 200 software organizations from 15 different countries, conducted by a testing services company named QASymphony, revealed that nearly half of the survey respondents had not implemented a test-first methodology in the applications they had developed.
Writing clean code requires a conscious effort of maintaining professionalism and following best industry standards throughout the stages of the software development process. Bad code should be avoided right from the onset of software project development, because the accumulation of bad debt through bad code can slow down software project completion and create future issues after the software has been deployed to production.
To avoid bad code, you have to be lazy, as the general saying goes that lazy programmers are the best and smartest programmers because they hate repetitive tasks, such as having to go back to fix issues that could have been prevented. Try to use programming styles and approaches that avoid writing bad code, to avoid having to rewrite your code in order to fix avoidable issues, bugs, or to pay technical debts.
Using the guidelines in C# coding conventions facilitates the mastery of writing clean, readable, easy to modify, and maintainable code. Use variable names that are descriptive and represent what they are used for, as shown in the following code:
int accountNumber;string firstName;
Also, having more than one statement or declaration on a line clogs readability. Comments should be on a new line and not at the end of the code. You can read more about C# coding conventions at: https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/inside-a-program/coding-conventions.
You should always try to write self-documenting code. This can be achieved through good programming style. W
