字幕表 動画を再生する
[MUSIC PLAYING]
JORDAN HAYASHI: Hello, and welcome for lecture 12, deploying and testing.
So last week, we talked about performance.
We talked about the trade-offs that you get
when you do some performance optimization, that
just being additional complexity.
We talked about a couple of different ways to test against performance, one
being the React Native perf monitors.
So it's built into your phone, and it allows
you to see how many frames per second you run.
We talked about the Chrome Performance Profiler,
which actually runs your JavaScript code within Chrome
and shows you a flame chart of all of the components that are rendering.
We talked about a few different common inefficiencies that we see in React.
One would be re-rendering too often, another
being unnecessarily changing props, which may actually
contribute to re-rendering too often.
And then lastly, just unnecessary logic.
And then we ended the lecture with a demo
of this animated API, which allows us to run
some calculations on the native side of things rather than within JavaScript.
So this week, we'll give a high-level talk about deploying apps.
So the way that you deploy in Expo is by building the app locally, and then
uploading it to the store.
Before you do that, you have to make sure to set the correct metadata
in your app.json file.
And you can find out exactly what those are at this Expo documentation link
here.
Then you go ahead and build the app using
this command-line utility called exp.
It's basically just an alternative to the XDE
because the XDE does not allow you to build the app within that GUI.
The way to do this is to install the script.
So you do npm install global exp, just like how
you install a bunch of other libraries.
You then build it by doing either build colon iOS or exp build android.
What that does is it actually sends your JavaScript--
your whole bundle, actually-- over to Expo's servers,
where it does the entire build.
And then Expo uploads that build to S3.
The way that you get that build onto your computer is to run this [? ex ?]
[? build ?] [? status, ?] which if you run it while it's building,
it will let you know it's still building.
But once it's done, it will spit out a URL for you,
which is the link to your app in Amazon's S3 storage system.
And then you can just cut and paste that into a browser
and go ahead and download that file.
Then you can upload it to the appropriate store.
So the way that you do that depends on whether you're doing iOS or Android.
And here's a couple of documentation links
that talk you through that process.
One great thing that you can do with Expo
is to deploy new JavaScript by republishing.
And that's called over-the-air update.
So you actually upload a new bundle because the way that your app works,
it's really just a shell that's running JavaScript code.
And so you can go ahead and download some new JavaScript from the web
and run that as your application.
And so by republishing from the XDE or using that exp script,
you can deploy a new JavaScript bundle and push it
over the air to your clients without having them redownload
the app from the app store itself.
Though if you want to change any application metadata,
like the name of it, then you're going to have to resubmit it to the store.
So doing this over-the-air update thing is very, very powerful,
but also slightly dangerous because you can actually upload JavaScript
that crashes your app and doesn't work.
And it won't actually be caught by their respective app store people
because they never see it.
It just goes straight to the cloud.
And then your users go ahead and download that.
And so how do we ensure that everything works as expected before deploying?
So you do that by testing.
And so when we use the word "testing," we generally
are referring to automated testing as opposed
to manual testing or doing quality assurance,
whereby you just open up your app manually and play
with all of the features that you have to make sure
that they work appropriately.
And so why might we want to do this?
Well, as your application grows in size, manual testing
gets more and more difficult. And more complexity
means there are more points of failure.
And so if you imagine if every single week,
you add 10 more features, that's growing linearly every week.
And so even though you keep adding the same number of features every week,
the amount that you have to test every week actually
goes up by the integral of that.
So you have a linear growth in the number of features
that you have to test every single week.
So by adding a test suite, you can ensure that you catch all of your bugs
before they get shipped.
Because the last thing that you want to do
is actually upload some broken code, because then all of your users
will get a broken app.
But how do we know which parts of our app to test?
There's this theoretical structure called the test pyramid.
And it determines a methodology for determining test scale or granularity.
So at the very bottom of the pyramid is what's called a unit test.
And this tests an individual unit of code.
And generally, that's either a function or a class or a method.
Then you have integration or service tests,
which allow you to test the integration of multiple of these pieces of code
and how they work together.
And this is completely independent of the UI.
Which brings us to the last one, the UI tests, or end to end.
And this allows us to test a feature thoroughly,
including the UI and network calls and everything.
So it's basically from one end of your code all the way to the other,
basically what a user would be doing themselves.
So how are we going to write some unit tests?
And so as we talked about in the last slide,
this is testing an individual unit of code,
like a function or a class or a method.
One great thing about unit tests is they're very, very granular.
So you know exactly where your code is breaking.
And that makes it very easy to tell what you need to go fix.
And so the very most basic unit test is just
a function that lets you know when any behavior is unexpected.
And so let's go ahead and write our first unit test.
So I'm going to make a new directory called testing.
And inside that, we're going to go ahead and write our first test.
And so let's write a very simple function, maybe something like sum.
And what sum does is it's just a function that
takes a couple of numbers.
Let's do function sum.
That takes an x and a y.
And let's just return the sum of those two numbers.
So return x plus y.
So pretty simple.
I'm pretty confident that this code does what I think it does.
Let's go ahead and write some tests anyway.
And so how might we go about doing that?
Well, we could write a function that does that.
Or we could just do console.assert, which is basically saying,
I'm going to assert that this thing is true, and if it's not true,
then throw an error.
And so let's just assert that sum of 1 and 1 gives us 2.
And if it doesn't, then we can throw an error that says error summing 1 and 1.
So we can save this and run it using Node.
And we get no output, which is a good thing because if there's no error,
it means our assert passed.
And so let's see what this looks like if we had written
assert that doesn't pass.
And so say we asserted that 1 and 1 was actually 3.
And let me go ahead and quiet this ESLint.
So if my now assert that sum of 1 and 1 is 3, then when we run this,
we get an assertion error.
It says assertion error.
Error summing 1 and 1.
And so we just effectively wrote our very first test.
So let's first fix this and make sure it passes and maybe write a couple
other tests.
We can do console.assert that summing 0 and 0 gives us 0.
And maybe a last one that summing 20 and 30 gives us 50.
20 and 30.
And we can just sanity check to make sure this actually works.
And it does.
Great.
So we just wrote our first simple test.
And so one thing that you may notice is that we have our tests directly
in the same file as our actual function.
And so if we were to write something like add with an x and y--
or not add, but maybe multiply, now if we want to add a test to this,
we're going to have to add some console.asserts.
And suddenly, this single file starts to get a little bit noisy.
And so just like we've done in other examples,
we might want to start breaking out things into separate files.
And so maybe the test should not be in the same exact file as the functions.
Maybe we should add it to its own test file.